SQL注入:floor()报错注入

基础知识:
floor(): 去除小数部分

rand(): 产生随机数

rand(x): 每个x对应一个固定的值,但是如果连续执行多次值会变化,不过也是可预测的

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

原理:
第一眼看起来有些懵逼,我们来从最基本的入手,最后在分析这个语句首先是floor()报错产生的条件:select count(*) ,floor(rand(0)*2)x from security.users group by x(自定义数据库的一张表)这里解释一下x是什么意思,可能有些同学不太熟悉sql语句,floor(rand(0)*2)x的x是为floor(rand(0)*2)添加了一个别名,就是x就等于floor(rand(0)*2),这样做的目的是让group by 和 floor(rand(0)*2)相遇(请原谅我这么解释).

这个payload的重点在group by a,也就是group by floor(rand(0)2)。首先,floor(rand(0)2)的意思是随机产生0或1。虽说是随机,但是它是有规律可循的。看看上面解释的rand(x),对于rand(0)而言,虽说是随机数,但是它的值与执行rand(0)的次数是意义对应的,即每一次执行rand(0)得到的结果都是固定的。基本是011011…这个序列。

那它为什么会报错呢?先来解释一下count(*)与group by是如何共同工作的。首先,系统会建立一个虚拟表:
SQL注入:floor()报错注入

SQL注入:floor()报错注入
好了,现在group by原理讲完了。那究竟是如何将其与floor联合起来,进行floor报错呢?

先来回顾一下payload: select count(), floor(rand(0)2) as a from information_schema.tables group by a;

总体是一个group by语句,只不过这里group by的是floor(rand(0)2)。这是一个表达式,每次运算的值都是随机的。还记得我刚刚说的floor(rand(0)2)的值序列开头是011011…吧?ok,下面开始运算。

首先,建立一张虚拟表:

SQL注入:floor()报错注入
继续进行group by。这是第四次floor运算了,根据刚刚那个011011序列,这次的值为0,在表中找是否有key为0的数据。当然没有,故应当插入一条新记录。在插入时进行floor运算(就像第一次group by那样),这时的值为1,并将count(*)置1。可是你会说,虚拟表中已经有了key为1的数据了啊。对,这就是问题所在了。此时就会抛出主键冗余的异常,也就是所谓的floor报错。

利用:select count(), concat((select database()), ‘-’, floor(rand(0)%2)) as a from information_schema.tables group by a; #将select database()换成你想要的东西!~