MySQL报错注入通过构造payload让信息通过错误提示回显出来,主要应用与查询不回现内容,会打印错误信息。这里主要讲一下十大报错中的floor报错。
floor()
payload构造:
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
关键函数说明:
rand函数可以产生一个0--1之间的随机数;
而当rand()有了参数之后,他会对所查询的每条数据产生一个随机数,但是从时间角度看每次给的随机数值是一样的,所以这个随机数是可以预测的,也叫伪随机数。
floor函数,其功能是“向下取整”,或者说“向下舍入”、“向零取舍”,即取不大于x的最大整数。
这里配合rand使用-->floor(rand(1)*2)
rand()返回的是0到1之间的随机数,乘2是为了让他返回0到2之间的随机数,组合floor()的取整,这里返回的值只能是0和1;
groud by 对数据进行分组;可以看到原表中pid有0、1和2三种值,通过order by分组可以更清晰看到。
count(*) 简单说就是个计数的函数;这里和group by合用用来计算每个分组出现的次数
该语句在运行时mysql会建立一个虚拟表,在查询数据的时候,首先查看该虚拟表中是否存在该分组,如果存在那么计数值加1,不存在则新建该分组。
报错分析
rand()的特殊性
select count(*) from test group by floor(rand(0)*2);
因为 rand 函数的特殊性(如果使用rand()的话,该值会被计算多次)。
在这里的意思就是,group by 进行分组时,floor(rand(0)*2)执行一次(查看分组是否存在),如果虚拟表中不在在该分组,那么在插入新分组的时候 floor(rand(0)*2)
就又计算了一次。
当我们使用floor(rand(0)*2)产生0和1两个随机数后,当在group by 对其进行分组的时候,首先遇到第一个值 0 ,发现 0 不存在,于是需要插入分组,就在这时,floor(rand(0)*2)
再次被触发,生成第二个值 1 ,因此最终插入虚拟表的也就是第二个值 1 ;然后遇到第三个值 1 ,因为已经存在分组 1 了,就直接计数加1(这时1的计数变为2);遇到第四个值 0 的时候,发现 0 不存在,于是又需要插入新分组,然后floor(rand(0)*2)
又被触发,生成第五个值 1 ,因此这时还是往虚拟表里插入分组 1 ,但是,分组 1 已经存在了!所以报错!