May 20, 2026·6 min read·2 visits
A vulnerability in the phpMyFAQ `/api/user/password/update` endpoint allows unauthenticated attackers to reset user passwords by supplying a valid username and email address. This lack of token verification leads to account lockouts and potential full account takeover.
phpMyFAQ versions prior to 4.1.3 contain a critical authentication bypass and account takeover vulnerability due to a flawed password recovery mechanism. The application processes password reset requests without requiring cryptographic token verification, allowing unauthenticated attackers to arbitrarily change passwords and lock out legitimate users.
phpMyFAQ is an open-source FAQ system. Versions prior to 4.1.3 contain a critical authentication bypass vulnerability in the password recovery mechanism. The vulnerability is tracked as GHSA-w9xh-5f39-vq89 and carries a CVSS 3.1 score of 7.1.
The flaw occurs in the UnauthorizedUserController class responsible for processing password reset requests. The application fails to implement standard security controls such as time-limited cryptographic tokens or email verification steps. This allows unauthenticated users to trigger password resets arbitrarily.
Attackers exploit this vulnerability by submitting HTTP PUT requests to the /api/user/password/update endpoint. Successful exploitation results in the immediate generation of a new password, which locks the legitimate user out of their account. This exposes the application to both denial-of-service and complete account takeover attacks.
The root cause of GHSA-w9xh-5f39-vq89 is the complete absence of cryptographic verification in the password recovery flow (CWE-640). Standard password recovery mechanisms require generating a secure, time-bound token that is sent to the user's email. The user must then present this token to authorize the password change.
The updatePassword() method in phpMyFAQ operates on a strictly deterministic logic path based on user input. It retrieves a username and email address from the incoming JSON payload and verifies if they match an existing record. If the match is successful, the function proceeds directly to generating and applying a new password.
The endpoint also lacks rate limiting or account enumeration protections. The API returns distinct error messages depending on whether the username exists or if the provided email matches the username. This verbose error handling facilitates automated enumeration of valid account credentials.
Once a valid pair is supplied, the application invokes $user->createPassword() and $user->changePassword(). The system alters the user's credentials in the database before the user confirms the action. This direct state modification represents a failure in control flow isolation (CWE-288).
The vulnerable logic resides in phpmyfaq/src/phpMyFAQ/Controller/Frontend/Api/UnauthorizedUserController.php, specifically within the updatePassword() method. The method binds to the user/password/update route and accepts unauthenticated HTTP PUT requests. The code extracts the username and email fields directly from the request payload.
The input undergoes basic sanitization via Filter::filterVar() and Filter::filterEmail(), but no cryptographic validation occurs. The application then checks if the user exists via $user->getUserByLogin($username). Following this, it verifies if the submitted email matches the stored email for that user.
The critical failure occurs immediately after the email verification block. The vulnerable code executes the following sequence:
if ($loginExist && $email === $user->getUserData('email')) {
$newPassword = $user->createPassword();
$user->changePassword($newPassword);
$mail->send();
}In the patched version (4.1.3), the developers refactored the password recovery flow to implement a two-step verification process. The application now generates a unique verification token and stores it in the database with an expiration timestamp. The password is only altered after the user navigates to a unique link containing this token and submits a new password.
Exploitation of GHSA-w9xh-5f39-vq89 requires network access to the target phpMyFAQ instance. The attacker does not need prior authentication or specific privileges. The attack operates in two distinct phases: credential enumeration and password reset triggering.
During the enumeration phase, the attacker submits crafted JSON payloads to the /api/user/password/update endpoint. By analyzing the HTTP responses, the attacker maps out valid users. A response of {"error":"The user doesn't exist"} indicates an invalid username, while {"error":"The email doesn't exist..."} confirms the username exists but the email is incorrect.
After identifying a valid username and email combination, the attacker sends the final exploitation payload:
curl -X PUT -H "Content-Type: application/json" \
-d '{"username":"admin","email":"admin@target.com"}' \
http://target/phpmyfaq/api/user/password/updateThe server processes the request, changes the user's password in the database, and responds with {"success":"Email has been sent."}. At this point, the legitimate user is locked out. If the attacker controls the target's email or intercepts the plaintext email communication, they acquire the newly generated password and gain full access to the account.
The primary impact of this vulnerability is the potential for complete account takeover. If an attacker targets the SuperAdmin account and intercepts the recovery email, they gain full administrative control over the phpMyFAQ installation. This allows them to modify system configurations, alter access controls, and access all internal data.
An attacker with administrative access compromises the confidentiality and integrity of all stored data. They can read private FAQ entries, extract user databases, and manipulate publicly visible content. This level of access facilitates further lateral movement or defacement of the application.
Even without email interception, the vulnerability provides a reliable mechanism for denial of service against specific accounts. By continuously triggering the password reset endpoint, an attacker persistently locks legitimate users out of their accounts. The system state is modified without the user's consent, disrupting normal operational availability.
The provided CVSS vector (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N) assigns a high integrity impact due to the unauthorized password modification. While the vector specifies 'None' for availability, the persistent lockout condition practically degrades user access. Organizations utilizing phpMyFAQ for internal knowledge management face significant disruption from this flaw.
The vendor addressed GHSA-w9xh-5f39-vq89 in phpMyFAQ version 4.1.3. Organizations must upgrade all instances running versions prior to 4.1.3 immediately. The patched release implements standard token-based verification for password resets, neutralizing the unauthenticated state modification.
If an immediate upgrade is unfeasible, administrators must implement temporary mitigations at the web application firewall (WAF) or reverse proxy level. Network administrators can create rules to block all HTTP PUT requests targeting the /api/user/password/update endpoint. This action disables the password reset functionality entirely, preventing exploitation while maintaining core application availability.
Security operations teams can detect exploitation attempts by monitoring HTTP access logs. Defenders should query for HTTP PUT requests directed at /api/user/password/update or /user/password/update. A high frequency of these requests originating from a single IP address indicates an active credential enumeration or brute-force attack.
Organizations should also review application logs for sudden, unexpected password change events, particularly for administrative accounts. Implementing rate limiting on all API endpoints via reverse proxies provides an additional layer of defense against automated enumeration tools.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
phpMyFAQ phpMyFAQ | < 4.1.3 | 4.1.3 |
| Attribute | Detail |
|---|---|
| CVSS Score | 7.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N) |
| CWE ID | CWE-640 (Weak Password Recovery Mechanism), CWE-288 |
| Attack Vector | Network |
| Authentication Required | None |
| Exploit Status | Proof of Concept available |
| Affected Component | UnauthorizedUserController::updatePassword() |
The system contains a mechanism for users to recover or change their passwords, but the mechanism is weak and can be bypassed or defeated.