CVE-2026-109321
Executive Summary
CVE-2026-109321 is a critical authentication weakness in the Grav grav-plugin-login-oauth plugin before version 1.4.3. The plugin provisions OAuth-linked accounts as ordinary Grav users using a predictable username of the form <provider>.<id> and a password consisting of an unsalted MD5 hash of the provider identifier, while leaving standard password login enabled. Any unauthenticated remote attacker who can learn or guess a provider identifier can reconstruct valid credentials and authenticate, potentially seizing administrative control of privileged accounts. With a CVSS score of 9.1, this represents a severe, remotely exploitable account takeover vulnerability.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability resides in the account provisioning logic of the Grav OAuth login plugin. When a user authenticates via an OAuth provider, the plugin creates a corresponding Grav user account rather than federating identity in a secure manner. Two core design flaws combine to produce the exploit:
Deterministic account naming: The generated username follows a fixed, predictable pattern —
<provider>.<id>. Because both the provider name and the provider-side identifier are frequently low-entropy or publicly observable (e.g., enumerable user IDs or publicly visible profile identifiers), the resulting username space is guessable.Weak, reproducible password derivation: The account password is set to an unsalted MD5 hash of the provider identifier. Unsalted MD5 is cryptographically broken for password storage; more critically here, the password is derivable from the same identifier used to construct the username. There is no server-side secret (pepper), salt, or randomness in the derivation. An attacker who knows or guesses the provider identifier can compute the exact MD5 digest and obtain the correct password.
Compounding the issue, the plugin does not disable conventional password-based login for these accounts. This means the weak derived credential can be submitted directly to the standard Grav login flow, bypassing the intended OAuth-only path entirely.
The root cause maps to CWE-1391 (Use of Weak Credentials): the system relies on predictable, low-entropy secrets that are reproducible by an attacker. No public proof-of-concept exists as of this writing, and the attack chain is inferred from the vulnerability class and the NVD description; no specific function, class, or endpoint names beyond those in the description are asserted here.
Exploitation Scenarios
No public PoC is available; the following attack chain is inferred strictly from the vulnerability class and the NVD description.
Reconnaissance / target identification. The attacker identifies Grav-based sites running the vulnerable
grav-plugin-login-oauthplugin before 1.4.3. Public fingerprinting (page content, plugin asset paths, or behavior of the OAuth login flow) allows enumeration of candidate targets. The attacker then attempts to learn or guess a target account's OAuth<provider>and provider-side<id>— sources include publicly visible OAuth profile identifiers, leaked references, or simple enumeration of low-entropy numeric IDs.Triggering the flaw class. The weakness is not triggered by an exotic payload but by credential reconstruction. Using the known provider and identifier, the attacker constructs the username
<provider>.<id>and derives the password by computing the unsalted MD5 hash of the same identifier. This reproduces exactly the credentials the plugin would have provisioned.Payload / execution method (vulnerability-class level). The attacker submits the reconstructed username and derived password to the standard Grav password login interface. Because password login is not disabled for these OAuth-provisioned accounts, authentication succeeds without any interaction with the OAuth provider.
Post-exploitation impact. Upon successful login, the attacker inherits the privileges of the compromised account. If the account is privileged (including administrative), the attacker gains administrative control of the Grav instance — enabling content manipulation, configuration changes, potential plugin/theme upload for code execution, and further lateral abuse within the CMS. Confidentiality and integrity impacts are rated High (C:H/I:H); availability is not directly impacted (A:N).
Impact Assessment
Per the CVSS v3.1 vector (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N), the vulnerability is network-exploitable, requires no privileges and no user interaction, and has low attack complexity. This yields a base score of 9.1 (Critical).
- Confidentiality (High): Full access to the compromised account's data, including the ability to read private content and configuration.
- Integrity (High): Administrative control permits modification of site content, users, and configuration.
- Availability (None): The vector does not score availability, though administrative access could in practice be leveraged to disrupt service.
Business impact: Any organization hosting a Grav site with the affected plugin is exposed to full account takeover, potentially leading to website defacement, data theft, content injection, or use of the CMS as a foothold. Because exploitation is unauthenticated and low-complexity, blast radius scales with site exposure. Administrative accounts are the highest-value targets.
EPSS: Not yet scored by FIRST.org at the time of writing. Patch confidence is 0/4 (no patch evidence from tracked sources); however, the NVD description references version 1.4.3 as the fixed version.
Detection Guidance
Sigma Rule
title: Grav Login-OAuth Deterministic Credential Login Attempt
id: 8f3a1c2e-6b74-4d1a-9c2e-gravoauth001
status: experimental
description: Detects authentication against a Grav instance using a username matching the OAuth provisioning pattern <provider>.<id>, indicative of CVE-2026-109321 exploitation.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-109321
author: valtersit.com
date: 2026/01/01
logsource:
category: authentication
product: grav
detection:
selection_user_pattern:
user|re: '^[a-zA-Z]+\\.[0-9A-Za-z_\\-]+$'
selection_login:
action: 'login'
condition: selection_login and selection_user_pattern
falsepositives:
- Legitimate OAuth-provisioned users logging in via password reset workflows
level: high
tags:
- attack.t1078
- cve.2026.109321
YARA Rule
rule CVE_2026_109321_Grav_OAuth_Weak_Credential
{
meta:
description = "Detects grav-plugin-login-oauth versions prior to 1.4.3 provisioning accounts with unsalted MD5 password derivation"
author = "valtersit.com"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-109321"
date = "2026-01-01"
strings:
$plugin = "grav-plugin-login-oauth" ascii wide nocase
$md5 = "md5" ascii wide nocase
$passwd = "password" ascii wide nocase
$version_old = "1.4.2" ascii wide
condition:
$plugin and $version_old and any of ($md5, $passwd)
}
Suricata IDS Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2026-109321 Grav login-oauth Deterministic Credential Login"; flow:to_server,established; http.method; content:"POST"; http.uri; content:"login"; http.request_body; content:"username="; pcre:"/username=[a-zA-Z]+\\.[0-9A-Za-z_\\-]+/"; classtype:attempted-admin; sid:2026109321; rev:1;)
Elastic Detection
sequence by source.ip with maxspan=5m
[authentication where event.action == "login_attempt" and user.name : "*.*"]
[authentication where event.action == "login_success" and user.name : "*.*"]
Splunk SPL Query
index=web sourcetype=grav_access
| search uri_path="*/login" method=POST
| rex field=form_data "username=(?<uname>[^\s&]+)"
| where match(uname, "^[a-zA-Z]+\.[0-9A-Za-z_\-]+$")
| stats count, values(src_ip) as source_ips by uname
| where count >= 1
Wazuh OSSEC Rule
<group name="grav,cve-2026-109321,">
<rule id="109321" level="12">
<decoded_as>web-accesslog</decoded_as>
<url>login</url>
<regex>username=[a-zA-Z]+\.[0-9A-Za-z_\-]+</regex>
<description>CVE-2026-109321: Possible Grav login-oauth deterministic credential login attempt</description>
<mitre>
<id>T1078</id>
</mitre>
<group>authentication_attack,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source).
1) Immediate mitigations
- Disable or remove the
grav-plugin-login-oauthplugin (version < 1.4.3) until it can be updated. - If OAuth login must remain active, disable conventional password login for OAuth-provisioned accounts as a temporary control.
- Audit existing Grav users for accounts whose usernames match the
<provider>.<id>pattern and reset/rotate their credentials. - Restrict access to the Grav administrative login interface via network controls, IP allowlisting, or a reverse-proxy authentication layer.
2) Patch / upgrade steps
- Upgrade
grav-plugin-login-oauthto version 1.4.3 or later, which the NVD description identifies as the fixed version. - After upgrade, force password resets for any accounts provisioned under the vulnerable version.
3) Long-term hardening
- Replace unsalted MD5 password derivation with a salted, slow hashing algorithm (e.g., bcrypt/Argon2) and never derive secrets from predictable identifiers.
- Generate account identifiers and secrets using cryptographically secure randomness rather than deterministic patterns.
- Enforce account provisioning through vetted identity flows and disable password login where OAuth federation is intended.
- Monitor authentication logs for usernames matching deterministic provider patterns.
References
- NVD — CVE-2026-109321: https://nvd.nist.gov/vuln/detail/CVE-2026-109321
- MITRE CWE-1391 — Use of Weak Credentials: https://cwe.mitre.org/data/definitions/1391.html
- MITRE ATT&CK T1078 — Valid Accounts: https://attack.mitre.org/techniques/T1078/
- Grav official project site (plugin update guidance): https://getgrav.org
- CISA Known Exploited Vulnerabilities Catalog — not listed at time of writing: https://www.cisa.gov/known-exploited-vulnerabilities-catalog
No exploit-in-the-wild evidence or threat actor campaign attribution is available at the time of writing.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.