sql报错注入原理分析

研究人员发现,使用group by子句结合rand()函数以及像count(*)这样的聚合函数,在SQL查询时会出现错误,且错误是随机产生的,这就产生了双重查询注入。

到底为什么floor()、rand(0)、count()、group by相结合,会产生这种错误呢?转载以前乌云一位哥的文章:

种子值为0的rand()函数的输出几乎固定为01101
sql报错注入原理分析
sql报错注入原理分析
sql报错注入原理分析sql报错注入原理分析

Okay let get it straight:
sql报错注入原理分析
关键点在于:在插入虚拟表的时候又要执行一次rand(0),而插入前后rand(0)的值可能出现改变。

rand(0):01101
执行rand(0)[ 第一次 ]:0 / 执行concat函数时,准备插入虚拟表时发现没有等于0的key,于是再执行rand(0)[ 第二次 ]:1
发现没有等于1的key。成功插入之。

执行rand(0)[ 第三次 ]:1 / 执行concat函数时,准备插入虚拟表时发现等于1的key,于是count直接+1

执行rand(0)[ 第四次 ]:0 / 执行concat函数时,准备插入虚拟表时发现没有等于0的key,于是再执行rand(0)[ 第五次 ]:1,却发现已经有了等于1的key。报错。

深层次的原因:
通过floor报错的方法来爆数据的本质是group by语句的报错。group by语句报错的原因是floor(random(0)*2)的不确定性,即可能为0也可能为1(group by key的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中则更新临时表中的数据;如果该key不存在于临时表中,则在临时表中插入key所在行的数据。group by floor(random(0)*2)出错的原因是key是个随机数,检测临时表中key是否存在时计算了一下floor(random(0)*2)可能为0,如果此时临时表只有key为1的行不存在key为0的行,那么数据库要将该条记录插入临时表,由于是随机数,插时又要计算一下随机值,此时floor(random(0)*2)结果可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。