SQL 时间盲注应该使用二分查找吗?

最近在写 SQL 时间盲注的自动化注入脚本时发现了一个奇怪的现象:猜数据时,穷举法居然比二分法快得多,这是为什么?

时间盲注常常使用形如 if(condition, sleep(5), 0) 的 SQL 语句逐字符猜测数据,当猜测成功时触发 sleep 函数.通过测量一次网络请求所花费的时间是否过大,可以知道是否猜对了数据,因此适合用于不论查询是成功还是出错页面内容都没有变化的网站,算是一种边信道攻击.所以,可以猜想,二分法虽然减少了总的猜测次数,但猜测成功的次数却增加了,而一旦猜测成功就会触发 sleep 函数,这也许就是二分法比穷举法更慢的原因.

可以做实验验证.这里就用 SQLi-LABS 的第一道时间盲注题目 Less-9 来测试了.为了加快爆出数据的速度,我删掉了一些数据, users 表的内容是这样的:

以下是用于对比的两个脚本,分别采用穷举法和二分法,会输出运行耗时和执行查询的次数.为了方便起见,我跳过了爆表名,列名的步骤,直接爆破 password 列的数据,并且把 3 行数据拼接到一起输出:

运行截图如下:

运行结果验证了我的猜想.虽然二分法将总查询次数从 1596 次大幅减少到了 266 次,但查询成功(触发 sleep 函数)的次数却从 24 次上升到了 92 次.考虑到注入的 SQL 语句里设定的延时是 2.5 秒,二分法理所应当地应该比穷举法更慢.

当然,这是相当理想化的结果,毕竟我的 SQLi-LABS 环境是搭建在本地的,并不能说明穷举法优于二分法.在真实世界的注入中,仍然应该使用二分法.考虑到攻击目标可能采取的各种限制措施,有必要在每次发送网络请求前都加上一段延时,这种情况下二分法应该会比穷举法更快.(当然,就算不考虑速度,二分法能够减少总查询次数也已经很大的优势了,毕竟请求越少,被目标封掉的风险也许就越小)


有意思的是, SQLmap 跑这个 Less-9 却相当的快,花不了几秒钟就能把整张表的数据都给爆出来.它是如何做到的呢?一番观察后我找到了原因,相当的...算了这是 Less-9 的源代码自己看吧

不知道是作者的疏忽还是有意为之,这 tm 就是个布尔注入啊查询失败时页面会多出一个元素,只是没有内容,对用户不可见而已

重新跑一遍 SQLmap: python sqlmap.py -u http://192.168.0.102/sqli-labs/Less-9/?id=1 -C password -T users -D security --dump -v 3 --flush-session --technique T --time-sec 3 这里我指定了注入方式为时间盲注,显示 payload, 并且把 sleep 的参数设为 3 秒(只能是整数).爆出数据总共花了 239 秒,和我自己写的二分法脚本的速度基本一致. Payload 也确实表明采用的是二分法:

(可以发现, SQLmap 的算法跟我的有一些细微的不同.对于每一位字符,它只会在疑似查到时做一次相等判断,不像我每轮循环都判断一次相等,这样应该可以进一步减少发送请求的数量.不过我按 SQLmap 的方式改写了脚本之后,发现在我的测试环境下,在查询速度方面并没有什么优势,这里就不多写了)

此外,你也许发现了,我的脚本用的 payload 仍然是联合查询那一套,所以在爆数据之前还得把列数给搞出来.而 SQLmap 的 payload 直接用了一个 AND 连接,不需要知道列数,用起来更方便些.

以上.

发表评论

电子邮件地址不会被公开。 必填项已用*标注