floor报错注入的原理

当count(*)和group by一起用,在执行的时候会创建一个类似于下面这样的虚拟表 查询值,count(*)
在这里插入图片描述

and select 1 from (select count(*),concat (database(),floor(rand(0)*2))x from information_schema.tables group by x)a)

select 1 from xxx...始终返回1

rand() 0<=返回值<1
select * from user 返回user数据有所有行数据
select floor(rand(0)*2) from user 返回user数据a(行总数)个1-2之间的伪随机数,也就是在一定次数的rand被执行时会得到一个不变的组,floor(rand(0)*2)6次为011 011

select count(*),table_name from information_schema.tables group by table_schema;计算一个库名出现了多少次

select count(*),concat('x',floor(rand(0)*2))x from information_schema.tables 结果为 数据库总表数,x0

select count(*),concat('x',floor(rand(0)*2))x from information_schema.tables group by x 

select 第一次
floor(rand(0)*2))=0 x0
group by会去找x0,没有就决定插入
group by决定插入却没有插入前,rand(0)会悄悄执行一次,结果为1(因为数据库总表数大于3,rand运行比group by快,也就是下一次rand执行,group by还没执行完第一次)
造成了一次select rand运行两次
floor(rand(0)*2))=1 x1
导致查询的值为x0不存在决定插入时,插入的值变为x1

select 的第二次
floor(rand(0)*2))=1 x1
此时查询的值为x1 ,在虚拟表里面查发现存在x1,于是导致count(*)+1 因为存在结果不需要group by执行插入,所以rand没有偷偷执行

select 第三次
floor(rand(0)*2))=0 x0
rand现在x0 group by就会查询不存在这个值就插入x0
但是rand此时会悄悄执行一次
floor(rand(0)*2))=1 x1
导致强行插入x1,此时报错,但由于mysql由内到外执行语句,所以concat('x',floor(rand(0)*2))被成功执行并返回x1结果,随着报错信息一起出来

rand(0)被执行两次的原因:
第一次执行rand为x0时,查询x0发现不存在就插入,插入会导致group by优化执行一次rand导致结果变为x1,最终导致查询的是x0插入结果为x1.所有但查询值存在时,rand不会被第二次执行,因为group没有优化执行。
最终的原因就是group by的优化执行策略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值