phpMyFAQ: The FAQ That Answered Too Much (CVE-2026-24422)
Jan 23, 2026·5 min read·1 visit
Executive Summary (TL;DR)
phpMyFAQ 3.x API endpoints default to over-sharing. An unauthenticated attacker can query the public API to retrieve a full dump of open questions—including those marked invisible—and the email addresses of the users who asked them. No authentication required, just a simple GET request.
An information disclosure vulnerability in phpMyFAQ's API allows unauthenticated attackers to harvest user email addresses and view hidden 'invisible' questions due to improper output filtering.
The Hook: Asking for Trouble
phpMyFAQ is exactly what it sounds like: a robust, open-source system for managing Frequently Asked Questions. It’s the kind of tool sysadmins drop onto a server to stop users from asking "How do I reset my password?" for the thousandth time. It’s supposed to be a repository of public knowledge, a library of safe, curated answers.
But here’s the thing about libraries: they usually keep the membership list private. You don't walk into a library, ask for a book, and get a list of everyone who’s ever checked it out along with their home addresses. Unfortunately, that’s effectively what phpMyFAQ was doing.
CVE-2026-24422 isn't a complex memory corruption bug or a state-sponsored backdoor. It's a classic case of "API Over-Generosity." The application assumed that if you asked for data, you probably deserved to see all of it. It turns out, letting the public API casually hand out user email addresses and internal questions marked "invisible" isn't a feature—it's a privacy nightmare waiting to happen.
The Flaw: Defaulting to Insecure
The root cause here is a logic error in how the API controllers handle data retrieval. In the world of secure coding, we preach "Principle of Least Privilege." If a user asks for a list of questions, you give them the public questions. You strip away metadata like internal IDs, moderator notes, and certainly the email address of the person who submitted the question.
phpMyFAQ missed the memo. The specific culprit lies in the OpenQuestionController::list() method. When this API endpoint is hit, it invokes the backend model's Question::getAll() method. In a well-architected system, this call would carry a flag like onlyVisible=true or sanitizeUser=true.
Instead, the method was invoked in a way that effectively set showAll to true. It didn't care if a question was marked isVisible = false (perhaps containing sensitive internal inquiries or unmoderated spam). It just grabbed the database rows and shoveled them into the JSON response. Worse, the serialization logic didn't think to redact the email field from the user object associated with comments, news, or FAQs. It was sending the full user record down the wire, trusting the frontend to just... not show it. But attackers don't use your frontend; they use curl.
The Code: The Smoking Gun
Let's look at the logic flow that causes this. While the exact variable names might vary slightly across versions, the architectural flaw looks something like this pseudocode representation of the vulnerable controller:
// Vulnerable OpenQuestionController
public function list(Request $request): JsonResponse
{
// CRITICAL FLAW: No filtering for visibility or user permissions
// The 'getAll' method defaults to fetching everything if not strictly constrained.
$questions = $this->question->getAll();
// The transformer simply dumps the object to array, including emails
return new JsonResponse($questions);
}The fix involves tightening this logic to explicitly check for visibility flags and sanitizing the output before serialization. The patched version enforces a visibility check:
// Patched Logic
public function list(Request $request): JsonResponse
{
// FIX: Explicitly request only visible items
$showAll = false;
if ($this->user->isAdmin()) {
$showAll = true;
}
$questions = $this->question->getAll($showAll);
// FIX: Use a transformer that strips PII (emails) for non-admins
return $this->transformResponse($questions);
}The difference is subtle in code but massive in impact. The original code trusted the database fetch; the fixed code distrusts the request context.
The Exploit: Asking Nicely
Exploiting this requires zero tools. You don't need Metasploit, Burp Suite, or a disassembler. You just need a web browser or a terminal. This is what we call a "low barrier to entry" vulnerability.
An attacker can simply enumerate the API endpoints. The most damaging ones identified are:
/api/v3.0/open-questions/api/v3.0/comments/api/v3.0/news/api/v3.0/faq
Here is the full "exploit chain" (and I use that term loosely, because it's just a GET request):
# 1. Target the 'open-questions' endpoint
# 2. Add an 'Accept-Language' header just to be polite (and ensure valid routing)
curl -i -H 'Accept-Language: en' \
http://target-phpmyfaq.com/api/v3.0/open-questionsThe Response:
Instead of a sanitized list, the server returns a JSON array containing objects where "isVisible": false questions are fully readable, and the "author" object contains "email": "victim@company.com".
From here, an attacker scripts a loop to dump the entire FAQ database, creating a tidy list of valid email addresses for a phishing campaign, perfectly targeted because they know exactly what questions these users have been asking.
The Impact: Why Panic?
You might think, "So what? It's just email addresses." In the modern threat landscape, an email address is half the battle.
1. Precision Phishing: If I know you asked a question on the internal FAQ about "How to configure the VPN for remote access," and I send you an email titled "Urgent: VPN Configuration Update" containing a malicious link, you are highly likely to click it. This vulnerability gives attackers the context needed to make phishing look legitimate.
2. Privacy Violation (GDPR): Leaking user emails is a direct violation of GDPR and other privacy statutes. For a corporate instance, this is a compliance nightmare.
3. Intelligence Leakage: The isVisible = false exposure is dangerous. Organizations often draft FAQs about upcoming mergers, security incidents, or policy changes and mark them as invisible until the release date. This vulnerability allows an attacker to peek behind the curtain and see organizational secrets before they are public.
Official Patches
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
phpMyFAQ phpMyFAQ | >= 3.0.0, < 3.2.5 | 3.2.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200 |
| Attack Vector | Network (API) |
| CVSS | 5.3 (Medium) |
| Impact | Information Disclosure |
| Privileges Required | None |
| Exploit Status | Public PoC Available |
MITRE ATT&CK Mapping
The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.