10 types of MySQL error-based sql injection
基本原理
在服务端会返回 MySQL 执行 SQL 时的错误信息的条件下可以构造报错注入来利用。
显然报错注入不是最方便的(利用SQL注入获取信息的)方式,但可能在某些情况下我们尝试用联合查询来获取数据时会遇到受阻的情况。
MySQL 报错注入利用的常见错误有以下几种:
1. BIGINT 等数据类型溢出
2. xpath 语法错误
3. concat+rand()+group_by()
导致主键重复
Type | Storage | Minimum Value | Maximum Value |
---|---|---|---|
(Bytes) | (Signed/Unsigned) | (Signed/Unsigned) | |
TINYINT | 1 | -128 | 127 |
0 | 255 | ||
SMALLINT | 2 | -32768 | 32767 |
0 | 65535 | ||
MEDIUMINT | 3 | -8388608 | 8388607 |
0 | 16777215 | ||
INT | 4 | -2147483648 | 2147483647 |
0 | 4294967295 | ||
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
0 | 18446744073709551615 |
在 MySQL 5.5 之前,整形溢出是不会报错的,根据官方文档说明 out-of-range-and-overflow ,只有版本号大于 5.5.5 时,才会报错。试着对最大数做加法运算,可以看到报错的具体情况:
mysql> select 18446744073709551615+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(18446744073709551615 + 1)'
在 MySQL 中,要使用这么大的数,并不需要输入这么长的数字进去,使用按位取反运算运算即可:
mysql> select ~0;
+----------------------+
| ~0 |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)
mysql> select ~0+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(~(0) + 1)'
如果一个查询成功返回,则其返回值为 0,进行逻辑非运算后可得 1,这个值是可以进行数学运算的:
mysql> select (select * from (select user())x);
+----------------------------------+
| (select * from (select user())x) |
+----------------------------------+
| root@localhost |
+----------------------------------+
1 row in set (0.00 sec)
mysql> select !(select * from (select user())x);
+-----------------------------------+
| !(select * from (select user())x) |
+-----------------------------------+
| 1 |
+-----------------------------------+
1 row in set (0.00 sec)
mysql> select !(select * from (select user())x)+1;
+-------------------------------------+
| !(select * from (select user())x)+1 |
+-------------------------------------+
| 2 |
+-------------------------------------+
参考资料
Error Based SQL Injection
http://dogewatch.github.io/2017/02/27/mysql-Error-Based-Injection/
Leave a Reply