报错注入
这里只有关于floor()rand()group by类型的
SQL报错注入就是利用数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。
函数 | 描述 |
---|---|
RAND() | 返回 0 到 1 的随机数 |
FLOOR(x) | 返回小于或等于 x 的最大整数 |
所谓的公式:
and (select 1 from (select count(*), concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
虚拟表
group by时, 会创建一个虚拟表统计主键
语句执行的时候会建立一个虚拟表,整个工作流程大致如下。开始查询数据时,读取数据库数据,查看虚拟表是否存在,不存在则插入新记录, 存在则count(*)字段直接加
key | count(*) |
---|---|
当数据行数大于3, floor(rand(0)*2)必定报错
使用floor(rand(0)*2)
时,返回的值一直为011011
- 查询前默认会建立空虚拟表
key | count(*) |
---|---|
- 取第一条记录,执行floor(rand(0)2),根据011011当顺序,第一个数据是0 (表中不存在),所以将floor(rand(0)2)插在key中
key | count(*) |
---|---|
floor(rand(0)*2) |
根据顺序,第二个数据是1,所以表变为
key | count(*) |
---|---|
1 | 1 |
继续计算,发现第三个数据为1,表变为
key | count(*) |
---|---|
1 | 2 |
- 再次计算时,数据又是0()表中不存在,所以floor(rand(0)*2)被插入表中
key | count(*) |
---|---|
1 | 2 |
floor(rand(0)*2) |
计算后发现为floor(rand(0)*2)的下一个值为1,但是主键是不能重复的,所以1无法被插入,数据库报错.
当数据行数大于3, floor(rand()*2)随机报错
不同于floor(rand(0)*2)
,floor(rand()*2)
的值是随机的,所以只有当主键有重复时,才有可能报错.