一、什么是SQL报错注入?

SQL报错注入就是让SQL函数报错,使得查询结果出现在错误信息中。

二、MySQL报错注入分类

1、数据类型溢出

2、xpath语法错误

3、主键重复

4、列名重复

5、几何函数缺少参数

三、具体说说上面几种报错类型

1、数据类型溢出

下面是MySQL官网的数字型数据类型的范围(MySQL5.5)

根据 https://dev.mysql.com/doc/refman/5.5/en/out-of-range-and-overflow.html文档可知,只有版本号大于5.5.5时会报错。

我们可以使用~0,用按位取反的方式得到最大值,在最大值基础上+1,得到最小的溢出值

exp函数差生类似的溢出错误

实战:

主要注意的是:在mysql>5.5.53的事后,exp报错不能返回结果,笔者这里用虚拟机中安装的phpstudy带的MySQL5.5.29版本测试成功,物理机安装的MySQL5.7.26测试失败。

2、xpath语法错误

从MySQL5.1.5开始提供两个XML查询和修改的函数, extractvalue()和updatexml()。

exreactvalue()负责在XML文件中按照xpath语法查询节点内容。
updatexml()则负责修改查询到的内容。

他们的第二个参数都要求符合Xpath语法的字符串,不满足语法就会报错,并将查询的结果放在报错信息中心。

extractvalue()的两个例子:

肯定有人好奇为什么报错来的信息并不完整,这是因为.和@都在xpath语法中有含义!当函数读取到一个xpath语法的符号后,开始解析但是因为解析不成功,随后报错。

解决方法:在语句前拼接一个xpath语法的特殊符号或者拼接一个能使xpath语法错误的特殊符号,例如~

xpath语法的链接放在这里:https://www.w3school.com.cn/xpath/xpath_syntax.asp

这里我们拼接一个xpath语法中的特殊含义字符,可以看到成功显示

updatexml的两个例子:

需要注意的是:extractvalue()和updatexml()这两个函数都有长度限制,都是32位。

3、主键重复

这里利用count()和group by遇到floor(rand(0)*2)产生的重复值时的报错的思路。

基本原理:

①首先介绍一下这几个函数
count() 统计个数
group by 按列分组
floor() 向下舍去小数位,保留整数位
rand() 随机函数

②rand(0)是一个稳定的序列不变的随机数(一组)

所以当我们使用floor()函数对rand()的值进行操作之后,也是一个稳定的序列

③使用group by进行count()进行统计的时候的过程

首先会创建一个虚拟表,包含两个部分,一个是主键,一个是计数器。

当开始查询数据的时候,首先看虚拟表中有没有这个主键,如果存在,计数器加1;
不存在的话,重新查询数据,插入主键值,并把计数器初始值设置为1。

有了上面的铺垫,我们来看下为什么下面的语句会报错

首先,我们去分组的时候根据的是floor(rand(0)*2)的值。

第一次查询,运算floor(rand(0)*2),我们group by 后面的值为0,主键并不存在,所以我们再次运算floor(rand(0)*2),但返回结果为1,把主键为1的值插入,并把计数器的初始值设置为1。

第二次查询,运算floor(rand(0)*2),这里其实已经是第三次调用floor(rand(0)*2)了,返回值为1,在虚拟表中存在主键为1的值,直接在计数器上加1,此时计数器值为2。

第三次查询,运算floor(rand(0)*2),这里其实已经是第四次调用floor(rand(0)*2)了,返回值为0,在虚拟表中不存在主键为0的值,需要添加主键为0的值,需要再次运算floor(rand(0)*2)后添加入主键的值中。但这次floor(rand(0)*2)是第五次,返回的值为1,本来是要插入的主键值中不存在的新值0,但是这次查询返回的值为1,发现主键为1的值已经存在,故报错。

4、列名重复

利用join()函数可以爆破列名

5、几何函数

MySQL中有一些几何函数,参数不满足要求就会报错,但是这些函数通常都是低版本MySQL适用。

有些几何函数,例如geometrycollection(),multipoint(),polygon(),multipolygon(),linestring(),multilinestring()等等。

MySQL 5.5.29 成功

MySQL 5.7.26 失败

因为MySQL版本问题,后续会写一篇关于fuzz报错函数的文章,这里剩下的几何函数类报错就不再赘述了。