phpMyFAQ, Stored XSS via SVG entity decoding bypass, CVE(N/A) (medium)

Listen to this Post

The vulnerability exists in phpMyFAQ’s SvgSanitizer::decodeAllEntities() method (lines 223-249). This function limits recursive entity decoding to only 5 iterations (maxIterations=5). Each iteration performs three actions: decoding numeric &NNN; entities, decoding hex &xHH; entities, and calling html_entity_decode() which resolves one level of & to &. An attacker can bypass both isSafe() detection and sanitize() removal by wrapping each character of “javascript:” in an href attribute with 5 levels of & encoding around numeric HTML entities. For example, &106; represents ‘j’. With 5 nested & levels, all 5 decoding iterations are consumed unwinding the & nesting, leaving the final &NNN; entities unresolved. The isSafe() method calls decodeAllEntities() but the pattern matching for “javascript:” fails because the decoded string still contains numeric entities. Thus isSafe() returns true and the malicious SVG is saved without sanitization. An authenticated user with FAQ_EDIT permission uploads the SVG via POST /admin/api/content/images. The file is stored in content/user/images/ with image/svg+xml MIME type. When served, the browser’s XML parser decodes the remaining numeric entities (e.g., &106; becomes ‘j’), reconstructing a valid javascript:alert(document.domain) link. Clicking the SVG executes arbitrary JavaScript in the phpMyFAQ origin. No

Scroll to Top