ZeroPath at Black Hat USA 2026

Brief Summary: CVE-2026-46364 — Unauthenticated SQL Injection in phpMyFAQ's Captcha API via User-Agent Header

A short review of CVE-2026-46364, a critical (CVSS 9.8) unauthenticated SQL injection in phpMyFAQ's BuiltinCaptcha class that allows attackers to extract credentials and tokens through crafted User-Agent headers sent to the public captcha API endpoint.

CVE Analysis

5 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-05-15

Brief Summary: CVE-2026-46364 — Unauthenticated SQL Injection in phpMyFAQ's Captcha API via User-Agent Header
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

An unauthenticated SQL injection in phpMyFAQ's public captcha API endpoint allows remote attackers to extract password hashes, admin tokens, and SMTP credentials from the underlying database using nothing more than a crafted User-Agent header. With a CVSS score of 9.8 and a publicly available proof of concept, this vulnerability represents a serious risk for any organization running phpMyFAQ versions prior to 4.1.2.

phpMyFAQ is an open source FAQ web application built for PHP 8.3+ with support for MySQL, PostgreSQL, and other database backends. Maintained by Thorsten Rinne under the MPL-2.0 license, the project has accumulated 616 stars and 263 forks on GitHub, serving organizations that need a self-hosted knowledge base solution. While not as widely deployed as commercial alternatives, phpMyFAQ fills an important niche in the open source ecosystem for teams that require full control over their FAQ infrastructure.

Technical Information

The vulnerability resides in the BuiltinCaptcha class, specifically in two methods: garbageCollector() and saveCaptcha(). Both methods construct SQL queries using sprintf() and interpolate the userAgent and ip fields directly from the incoming HTTP request. Neither field passes through Database::escape() or a prepared statement before reaching the query.

On every request to the public GET /api/captcha endpoint, the getCaptchaImage() function unconditionally calls both vulnerable methods. This creates two distinct SQL injection sinks per request:

  1. A DELETE query in garbageCollector()
  2. An INSERT query in saveCaptcha()

The endpoint requires no authentication, no CSRF token, no session, and enforces no rate limiting. Any remote attacker can reach both sinks by simply issuing a GET request with a malicious User-Agent header.

Exploitation Flow

MySQL's query() method executes only one statement per call, which prevents query stacking. However, time-based blind SQL injection remains fully effective. An attacker injects SQL functions such as SLEEP() or BENCHMARK() into the User-Agent header value.

The dual sink nature of the vulnerability provides a clear confirmation signal. A baseline request to the captcha endpoint completes in approximately 0.147 seconds. When the User-Agent header contains a payload like x' OR SLEEP(2) OR 'x, the response takes approximately 4.093 seconds. The four-second delay (rather than two) confirms that the SLEEP(2) command executes twice: once in the DELETE statement and once in the INSERT statement.

From there, attackers use single-bit boolean extraction techniques to iterate through database rows and exfiltrate sensitive data. The primary targets are:

  • The faquser table, which contains bcrypt password hashes for all registered users
  • The faqconfig table, which stores the main.phpMyFAQToken admin token and SMTP credentials

Beyond data exfiltration, payloads targeting the DELETE path can wipe arbitrary rows within the database connection's scope. This could destroy the entire faqcaptcha table, effectively locking out legitimate users from captcha-protected functionality.

For organizations maintaining custom forks or unable to upgrade immediately, the fix involves routing all user-controlled fields through Database::escape() before interpolation. The patched garbageCollector() implementation should follow this pattern:

$db = $this->configuration->getDb(); $userAgent = $db->escape($this->userAgent); $language = $db->escape($this->configuration->getLanguage()->getLanguage()); $ip = $db->escape($this->ip); $delete = sprintf( "DELETE FROM %sfaqcaptcha WHERE useragent = '%s' AND language = '%s' AND ip = '%s'", Database::getTablePrefix(), $userAgent, $language, $ip ); $db->query($delete);

The same escaping pattern must be applied to saveCaptcha() and any other code paths that use sprintf to construct SQL statements with user-controlled input.

Affected Systems and Versions

All versions of phpMyFAQ prior to 4.1.2 are affected. Version 4.1.2, released on April 28, 2026, addresses this vulnerability. The flaw is present in any deployment where the GET /api/captcha endpoint is publicly reachable, which is the default configuration.

Vendor Security History

phpMyFAQ has seen a notable cluster of security disclosures in early 2026, suggesting the codebase is undergoing active security review. The following table summarizes recent CVEs:

CVE IdentifierAffected VersionsDescriptionSeverity
CVE-2026-32629Prior to 4.1.1Unauthenticated attacker can submit a guest FAQ with an emailUnknown
CVE-2026-27836Prior to 4.0.18WebAuthn prepare endpoint creates new active userUnknown
CVE-2026-244224.0.16 and belowPublic API endpoints improperly expose sensitive user information7.5 HIGH
CVE-2026-244204.0.16 and belowAuthenticated user without dlattachment permission accessUnknown

The vendor has been responsive in issuing patches for each of these disclosures, which is a positive signal for organizations evaluating the project's security posture.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Jira
  • Linear
  • Slack
  • Security Compass
Security magnifying glass visualization