导语
一直使用mysql的报错注入,但是不清楚它的原理是什么,为什么会出现报错,我们使用到了floor(),rand(),count(*)三个函数,每个函数起到了什么作用,经过查阅资料,搞懂了报错的原因,现在总结一下。
正文
0x01 原因
当我们这样使用SQL语句的时候就会出现报错。
经过查阅资料发现,我们使用floor(rand(0)*2)时,报错的条件是必须有三条以上的数据必定会出现报错。
但是当我们使用floor(rand()*2)时,结果就是随机的了,报错的几率和我们数据库中查询数据的条数没有了绝对的关系。
0x02 rand()
可以发现查询的两条记录都是随机的结果,没有什么规律。
但是使用了随机因子以后floor(rand(0)*2)
可以看出来,两次查询的结果完全一样,01101100111011,都是这样的一个组合。说明我们使用了floor(rand(0)*2)是有规律的,那我们报错的原因又是什么呢。
0x03 count()和group by
当我们在使用语句select name,count(*) from webstar.my_article group by name;
进行查询的时候,会统计出每个分组里面的数据条数。
可以看到,辛弃疾的数据一共有两条,其他的都是一条。查阅资料知道了,当我们使用这条语句进行查询的时的流程是:
1.先建立一个虚拟表;
2.开始查询的时候,取出数据库数据,看看虚拟表中是否存在,如果存在就给count(*)字段加1,不存在就插入新纪录,创建一个key。
当我们使用rand()进行查询的时候,该值会被计算多次,当我们使用group by语句时,floor(rand(0)2)会被执行一次,如果虚拟表中不存在记录,插入虚表前再计算一次,由于floor(rand(0)2)的值是定性的,所以导致问题产生。
0x04 rand(0)*2报错原理
1.首先建立了一个虚表;
2.取第一条数据,执行floor(rand(0)*2),结果为0(1),查询虚表,发现键值0不存在,在进行一次计算,结果为1(2),插入到表中;
3.取出第二条数据,执行floor(rand(0)2),结果为1(3),查询虚表,记录存在,直接count()加一;
4.取出第三条数据,执行floor(rand(0)*2),结果为0(4),查询虚表,发现不存在键值0,在进行一次计算,结果1(5),插入到虚表中作为虚表的主键,与之前的1冲突,这时候就会报错了。
0x05 rand()*2报错原理
其实rand()2报错原理与之前的rand(0)2原理相同,主要是要保证在开始的查询结果中,不能让虚表中存在0,1键值,不然之后无论多少条记录都不会在报错了,例如随机数:0100011在第一次取数据时插入了1,第二次取数据时插入了0,以后不会再存在主键重复的可能,就不会再报错了,因为表中已经存在0和1这两个数据。
附带一些常用的报错语句:
select count(),concat((select database()),floor(rand()5))a from information_schema.tables group by a
union select 1,(select (concat(0x22,(select version()),0x22)))a from information_schema.tables group by a–+-
union select 1 from (select count(),concat(floor(rand(0)2),(select table_name from information_schema.tables where table_schema=database() limit 0,1))a from information_schema.tables group by a)b–+-
模板:select count(),concat(floor(rand()2),(select语句查询))a from information_schema.tables group by a
总结
其实我们发现mysql的报错注入,rand(),group by,count(),这三个条件缺一不可,否则就无法报错,还有如果使用rand(0)*2,保证数据库数据在三条以上,因为在第三次的时候会出现报错。