← Back to PullLight
CVE-2026-33352 CVSS 9.8 Critical PHP — WWBN/AVideo <= 14.2

AVideo — SQL Injection via Backslash-Escape Bypass

WWBN/AVideo <= 14.2 has SQL injection in objects/category.php — the code uses str_replace("'", "'", $value) as a SQL injection mitigation, but this only strips single quotes, not backslashes. An attacker injects a backslash to break out of a string context and execute arbitrary SQL.

CVSS 9.8 / 10.0
CWE CWE-89 (SQL Injection)
Package WWBN/AVideo (<= 14.2)
Published Mar 23, 2026
~2.1k GitHub stars (WWBN/AVideo)
Self-hosted video platform PHP-based, ~10k+ deployments
Attack surface any user-supplied value in category operations
EPSS 0.03% (low exploitability score, but trivially exploitable over network)
// what happened
  • Affected: WWBN/AVideo <= 14.2 — PHP video platform (self-hosted, widely deployed)
  • Attack vector: objects/category.php uses str_replace("'", "'", $value) as a SQL injection mitigation — this replaces single quotes with escaped quotes, but doesn't handle backslashes. An attacker injects a backslash to escape the string delimiter: value = "test' OR 1=1 --" becomes value = "test'' OR 1=1 --" after str_replace, but value = "test\\' OR 1=1 --" breaks the string context because the backslash itself isn't escaped.
  • Impact: Full SQL injection — attacker can read, modify, or delete any data in the database. On many deployments this includes admin credentials, video metadata, and user data.
  • Fix: Use $global['mysqli']->real_escape_string() instead of str_replace. Commit 206d38e97b8c patches the vulnerability.
  • Attacker model: Any unauthenticated user who can submit values to category creation/editing endpoints — no account required.

Base Score
9.8 Critical
Attack Vector (AV)
Network — unauthenticated HTTP requests to category endpoints
Attack Complexity (AC)
Low — straightforward HTTP request with crafted payload
Privileges Required (PR)
None — no authentication required
User Interaction (UI)
None
Scope (S)
Unchanged
Confidentiality (C)
High — full database read access
Integrity (I)
High — data can be modified or deleted
Availability (A)
High — database can be locked or dropped
Vector String
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

objects/category.php — WWBN/AVideo <= 14.2 WWBN/AVideo <= 14.2 — str_replace("'", "'") attempts SQL injection mitigation but misses backslashes // VULNERABLE: str_replace only escapes single quotes, not backslashes // MySQL interprets \" as an escaped character, not as literal backslash // So an attacker injects \" to break out of the string context // Vulnerable pattern in category.php (lines ~388-397): $sql = "SELECT * FROM category WHERE name = '" . str_replace("'", "'", $_POST['name']) . "'"; // If attacker sends: name = test\\' OR 1=1 -- // str_replace results in: name = test\\'' OR 1=1 -- // In MySQL: test\\ = literal backslash + t // ' OR 1=1 -- = closes string and executes injected SQL // The backslash that wasn't escaped allows the single quote // to escape the string delimiter instead of being escaped itself // Example attack payload: // name=test\\\\' OR 1=1 -- // After str_replace: test\\\\'' OR 1=1 -- // MySQL sees: test\\ + \\' (escaped quote) + OR 1=1 --
How the backslash bypass works // The str_replace fix looks like a security improvement // Developer intent: replace ' with '' (standard SQL escaping) // But they forgot to escape the backslash first // MySQL string escape rules: // '' becomes ' (escaped quote) // \\' becomes \\' (backslash + quote, NOT escaped quote) // ' becomes ' (unescaped quote, closes string) // str_replace("'", "'", "test\\'") → "test\\''" // MySQL interprets: "test\\" = "test\" (backslash + t) // "' OR 1=1 --" = string that closes, then injected SQL // The ONLY correct PHP/MySQL escaping: // $global['mysqli']->real_escape_string($_POST['name']) // → escapes \n, \r, \t, \b, \r, \u0000, ", ', and \\
Exploitation payload construction // Step-by-step attack payload: // Original intent: inject " OR 1=1 -- as the name parameter // Step 1: Send name = test // str_replace: test (no quotes, no change) // SQL: "SELECT * FROM category WHERE name = 'test'" ← safe // Step 2: Try name = test' OR 1=1 -- // str_replace: test'' OR 1=1 -- // SQL: "SELECT * FROM category WHERE name = 'test'' OR 1=1 --'" ← broken syntax, not exploitable // Step 3: Use backslash bypass: name = test\" // str_replace: test\" (doesn't match any single quote) // SQL: "SELECT * FROM category WHERE name = 'test\" OR 1=1 --'" // MySQL parses: name = 'test' then \" is not an escape sequence // SQL continues: OR 1=1 --' (injected SQL, comment ignored due to bad syntax) // Step 4: Correct bypass: name = test' OR 1=1 -- // str_replace makes it: test'' OR 1=1 -- // But with crafted injection: name = test\\' OR 1=1 -- // str_replace: test\\'' OR 1=1 -- // MySQL: test\\ (literal "\"), '' (escaped quote), then: OR 1=1 --
objects/category.php — WWBN/AVideo (fixed) WWBN/AVideo — commit 206d38e97b8c replaces str_replace with real_escape_string // FIX: Use mysqli->real_escape_string() instead of str_replace() // real_escape_string correctly escapes ALL special characters: // \n, \r, \t, \b, \u0000, ", ', and \\\\ // BEFORE (vulnerable): $sql = "SELECT * FROM category WHERE name = '" . str_replace("'", "'", $_POST['name']) . "'"; // AFTER (fixed): $sql = "SELECT * FROM category WHERE name = '" . $global['mysqli']->real_escape_string($_POST['name']) . "'"; // Now attack payloads are safely escaped: // name=test\\' OR 1=1 -- // becomes: test\\' OR 1=1 -- (backslash escaped to \\, quote to \\\\') // SQL: SELECT * FROM category WHERE name = 'test\\'' OR 1=1 --' // MySQL sees: name = 'test\\' (literal backslash + quote), then: OR 1=1 -- as string data // ← Injection blocked. No SQL execution.
// fix details
The fix commit 206d38e97b8c replaces the str_replace("'", "'", ...) calls in objects/category.php with proper MySQLi real_escape_string() calls. real_escape_string() is MySQL's built-in escaping function — it handles \b, \n, \r, \t, \u0000, ", ', and \u005C (backslash) correctly. There is no backdoor for a custom string-replacement approach to match this.
Fix commit — 206d38e97b8c (AVideo repo) WWBN/AVideo — 206d38e97b8c SQL injection fix // Key change: real_escape_string replaces str_replace // Before: str_replace("'", "'", $value) // After: $global['mysqli']->real_escape_string($value) // This pattern should be applied everywhere user input reaches a SQL query // Audit all files in objects/ directory for similar str_replace patterns // PHP built-in: mysqli_real_escape_string($conn, $str) // Preferred: $mysqli->real_escape_string($str)
// root cause
The developer applied a custom SQL escaping pattern: str_replace("'", "'", $value). This replaces single quotes with escaped quotes ('' in SQL), which is standard SQL string literal escaping. However, it only handles single quotes — it does not escape backslashes. MySQL interprets a backslash as an escape character: \\ is a literal backslash, and \" is a literal quote inside a string, not a string delimiter. When an attacker sends a value containing \\', the backslash prevents the quote from being escaped by the str_replace, and the quote then closes the string literal in the SQL query. The attacker has broken out of the string context and can inject arbitrary SQL. Proper escaping uses the database driver's built-in escaping function, which handles all special characters including backslashes.

From a category name field to full database compromise
1
Attacker identifies a WWBN/AVideo deployment <= 14.2 and finds a category creation or editing endpoint (e.g., the admin panel or an exposed API for category management).
2
Attacker sends a crafted category name value containing \\'. The str_replace("'", "'") processes the value — the backslash is left untouched (str_replace only handles single quotes). The single quote after the backslash is not escaped because the backslash broke the pattern.
3
The processed value reaches the SQL query string as 'value\\' + injected_SQL + '--'. MySQL parses the backslash-quote pair as an escaped quote inside the string, not as a string delimiter — the string stays open, and the following SQL is interpreted as query code.
4
Attacker injects OR 1=1 -- to bypass any WHERE conditions, or UNION SELECT to extract data from other tables, or DROP TABLE to destroy data. Full SQL injection confirmed.
5
Attacker reads admin credentials, user data, video metadata, or any other database content. In many self-hosted deployments, database access also means access to filesystem via SELECT INTO OUTFILE or similar.
AVideo powers self-hosted video platforms — database compromise affects all users
  • Self-hosted video platforms: AVideo is a self-hosted solution — deployments on university servers, corporate intranets, community platforms. An attacker compromising one installation gains access to all videos, user data, and admin credentials for that deployment.
  • No authentication required: The vulnerability is reachable without any account. Any visitor to an AVideo installation can send crafted category values to the appropriate endpoint.
  • Admin credential theft: AVideo's admin credentials are stored in the same database. After SQL injection, the attacker can extract admin password hashes, crack them offline, and gain full admin access to the video platform.
  • Widespread deployments: With ~2.1k GitHub stars and PHP's popularity for self-hosted solutions, there are likely thousands of active AVideo installations — many running outdated versions.
  • The fix looked correct: The developer added str_replace("'", "'") as a security measure — it follows a pattern commonly taught in basic SQL injection tutorials. The vulnerability is the absence of backslash handling, which is hard to spot without deep knowledge of MySQL's escape sequences.
Unauthenticated SQL Injection
No account required — any visitor can send the exploit payload. This makes mass scanning for vulnerable AVideo installations trivial.
Full Database Compromise
Attacker can read, modify, or delete any data in the database — users, videos, admin credentials, configuration.
Custom Escaping Is Never Safe
The str_replace("'", "'") pattern looks like a security fix but only covers quotes. MySQL escaping rules require handling backslashes too — use the database driver's built-in function.
Widespread AVideo Adoption
~2.1k GitHub stars, self-hosted PHP deployments on universities, companies, and community platforms. Many are running outdated AVideo versions.

🔴 PullLight — Critical Finding
[CRITICAL] SQL Injection via Backslash-Escape Bypass — objects/category.php

objects/category.php uses str_replace("'", "'", $value) as SQL injection mitigation. This only escapes single quotes — it does not escape backslashes. MySQL interprets \\ as a literal backslash and \" (backslash + quote) as a literal quote inside a string, not a string delimiter. An attacker injects a backslash before a quote: test\\' OR 1=1 --. After str_replace: test\\'' OR 1=1 --. MySQL sees: test\\_ (backslash + t + backslash + quote is parsed as a literal backslash-quote pair), then the remaining SQL executes. This is CWE-89 (SQL Injection) with CVSS 9.8. No authentication required.

Use $global['mysqli']->real_escape_string($value) instead. Or switch to prepared statements entirely.
→ Fix: Replace str_replace("'", "'", $value) with $global['mysqli']->real_escape_string($value). Audit all other str_replace-based SQL escaping patterns in the codebase — this vulnerability pattern is likely present elsewhere.

Four reasons this vulnerability hides from line-by-line review

  • The str_replace fix looks intentional and security-focused. A reviewer sees str_replace("'", "'", ...) and recognizes it as SQL escaping — a deliberate security measure. It doesn't look like a bug; it looks like a fix that prevents SQL injection. The absence of backslash handling is invisible unless you know to look for it.
  • PHP's double-escape syntax confuses the pattern. str_replace("'", "'") appears as str_replace("'", "''") in some code examples — with two single quotes in the replacement string. Reviewers may mentally normalize this to the correct '' escaping pattern and approve it as correct.
  • MySQL's backslash-escape rules are a niche detail. Most developers learn that single quotes in SQL strings need to be escaped as ''. Not as many are trained on the interaction between backslashes and quote escaping in SQL string literals — the specific sequence \\' that defeats simple str_replace-based escaping.
  • The vulnerable code sits in the data layer, not business logic. objects/category.php is a data access file. Code reviewers typically focus on business logic and authentication checks. Data-layer escaping patterns are reviewed less carefully and often assumed to be correct.

What makes this a PullLight-specialized catch

  • MySQL escape sequence modeling: PullLight understands MySQL's escape sequence behavior — that \\ is a literal backslash and that backslash-quote sequences in user input can break string delimiter boundaries in concatenation-based SQL.
  • Custom escaping anti-pattern detection: PullLight flags any use of string replacement as a SQL injection mitigation — custom escaping functions never handle all special characters correctly. Only built-in database driver escaping is acceptable.
  • CVSS 9.1+ severity calibration: PullLight correctly scores unauthenticated SQL injection as critical based on no auth required + full database compromise potential.
  • Fix precision: PullLight identifies the specific fix (real_escape_string() instead of str_replace) rather than vague "sanitize inputs" advice.

Mar 23, 2026 CVE-2026-33352 published. GHSA-mcj5-6qr4-95fj disclosed. WWBN/AVideo 14.3+ released with patch. CVSS 9.8 confirmed. Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
Mar 23, 2026 Fix commit 206d38e97b8c merged — replaces str_replace with real_escape_string in objects/category.php.
Mar 2026 CVE-2026-33352 added to NVD. EPSS score: 0.03% (low, but exploitability is trivially achievable over the network without authentication).
Jun 2026 PullLight documents CVE-2026-33352 as 26th CVE case study — demonstrating backslash-escape SQL injection bypass.

Don't let custom escaping bypass your SQL injection protections

More CVE Case Studies