Skip to main content

sql_char_decompose

Function sql_char_decompose 

Source
pub fn sql_char_decompose(payload: &str) -> String
Expand description

SQL CHAR()-function decomposition — converts every single-quoted string literal in the payload to a CHAR(N1,N2,...) function call with one codepoint per argument.

Input 'admin' → output CHAR(97,100,109,105,110)

Bypass mechanism: distinct from sql_concat_split (which produces CONCAT('a','d',...)) — CHAR() takes integer codepoints, not single- char strings, so the payload contains NO single-quoted ASCII tokens at all. WAF rules that match string-literal patterns ('admin', 'password', '/etc/passwd', 'or 1') and CONCAT-shaped patterns (CONCAT\(.{,8}\)) both miss this form. Most CRS rules through PL3 do NOT pattern-match raw CHAR() — it’s been the sqlmap default for over a decade and has been deemed too noisy to block.

Supported by MySQL, MariaDB (native CHAR()), MSSQL (CHAR()). For Postgres / Oracle, the equivalent is CHR() — out of scope here; a sibling chr_decompose could ship later.

Edge cases:

  • Empty literals ('') pass through as '' unchanged. CHAR() with zero args evaluates to NULL in MySQL — silently flipping a comparison like pass='' OR 1=1 into pass=NULL OR 1=1 would break the auth bypass (= NULL is never TRUE). Preserve the empty-string identity.
  • Multi-byte UTF-8 chars produce a single CHAR(codepoint) per chars() iteration — for codepoints > 255, MySQL’s CHAR() returns per-byte; the codepoint may not round-trip exactly. Most SQLi payloads use ASCII literals — this matters only for adversarial inputs.
  • Unbalanced opening quote: emitted unchanged.

Context: SQL injection with string-literal targets that are blocklisted (admin, password, paths, hostnames).