PortSwigger SQL注入LAB11
欢迎来到PortSwigger SQL注入的LAB11,这道LAB在某些地方跟LAB10是非常相似的,那么我们现在开始吧:
【本篇目标】
- 理解并掌握带条件错误的SQL盲注的技能
- 通过SQL盲注来获取所需administrator的密码,并完成登录
一、理解cookie在此处的作用
我们先来看 LAB11 的题目,他说应用使用了 cookie 进行了跟踪分析,不同于 LAB10,SQL 的查询结果不仅不会返回,也不会显示错误信息,而且页面也不会显示 "Welcome back" 的消息了。
也就是说相较于 LAB10,我们现在是"全盲"状态。还有一点在题目中的提示中写出了,本次 LAB 中的数据库类型为 Oracle。
最终的目标还是老样子,从users表中获取administrator用户的密码并成功登录
既然如此,那我们就要尝试主动引起报错。现在来试一下:如果把 cookie 查询的语句破坏掉会发生什么,我们在 TrackingId 值的后面加一个 ' 来将其破坏。
我们可以看到返回了服务器内部错误,这说明服务器的内部错误提示没有被屏蔽,那么我们就可以通过故意构造语法错误来进行盲注。
二、获取密码长度
2.1 理解并构造条件错误
既然知道服务器并没有屏蔽语法错误导致的服务器内部错误,那么我们就开始构建条件语句吧:
' AND (SELECT CASE WHEN 1 = 2 THEN TO_CHAR(1/0) ELSE 'a' END FROM DUAL) = 'a' --
这段语句是什么意思呢?首先第一个 AND 把服务器验证 TrackingId 和后面我们自己编写的语句进行了布尔连接。
接下来我们看括号内的内容,括号内的意思是去 DUAL 表中判断 1 是否等于 2,如果等于的话,则执行 TO_CHAR(1/0) 语句;如果 1 不等于 2,则会输出一个 a。END 结束 CASE 之后与 a 进行对比,若 a 等于 a,则会产生一个 true 的布尔值。
至于 TO_CHAR(1/0),就是调用了 TO_CHAR 函数来把 1 除以 0 的结果转化为 CHAR 数据类型。由于 1 除以 0 是非法计算,所以此处是一个故意制造的错误。
2.2 构建密码长度获取语句
既然我们了解了如何构造条件错误,那么接下来我们尝试获取密码的长度:
' AND (SELECT CASE WHEN LENGTH(password) > 1 THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username = 'administrator') = 'a' --
这样,如果密码长度大于 1,CASE 就会跳入我们故意写的错误分支中,服务器则会返回内部错误;若密码长度不大于 1,CASE 会跳入后面的输出 a 中,与后面的 a 进行比较之后,服务器就会返回正常响应。
注意:
在某些数据库或字符集下,LENGTH() 按字节计数。如果目标数据可能包含多字节字符,建议结合题目环境确认是否需要使用 CHAR_LENGTH() 或同类函数。
这里我们可以看到服务器成功回显了 "Internal Server Error",说明 administrator 密码的长度大于 1,那么我们可以不断递增 1 的值来获得密码确切的位数。
2.3 使用Intruder进行爆破
接下来我们按照LAB10的方法设置数字1为Payload,经将其的范围设置在1-30区间中,然后Start Attack开始攻击
结束之后,我们通过判断Length的突变,可以找到本次攻击的临界点,在Payload值为20的时候,服务器不再出现内部错误,说明administrator的密码长度20。
三、获取密码
3.1 构建密码获取语句
还是像 LAB10 一样,我们把刚刚的语句稍微改一下就可以利用它对密码进行爆破了:
' AND (SELECT CASE WHEN SUBSTR(password, 1, 1) = 'a' THEN TO_CHAR(1/0) ELSE 'a' END FROM users WHERE username = 'administrator') = 'a' --
这里我们还是像 LAB10 一样,使用了 Oracle 的 SUBSTR 函数来获取 password 中的第一个字符并与 'a' 进行对比;若相等,则会跳入我们故意写的错误分支中,服务器则会返回内部错误;若不相等,CASE 会跳入后面的输出 a 中,与后面的 a 进行比较之后,服务器就会返回正常响应。
注意:
正如我开头所说的,这次 LAB 的数据库为 Oracle,所以获取第一个字符的函数为 SUBSTR(*,*,*),而不是 SUBSTRING(*,*,*)。
3.2 使用Intruder进行爆破
我们将刚刚构建好的语句发送至 Intruder,然后把 Attack Type 切换为 Cluster bomb(集束炸弹),并将代表第一个字符的 "1" 设置为第一个 Payload,把用于比较的 "a" 设置为第二个 Payload。
接下来把第一个 Payload 的类型设置为 Numbers,并把范围设为 1-20;再把第二个 Payload 的类型设置为 Simple list,并从 Add from list 中添加小写 a-z、大写 A-Z 以及数字 0-9 到列表中(Burp Suite 社区版不支持 Add from list 功能)。
点击 Start attack 开始攻击并分析结果:
3.3 拼接密码
现在我们就已经得知密码每一位的值了,这里我使用记事本把它们拼接起来:
至此,我们得出了最终的密码 46lx0pii9dxqeo26ralx。
四、登陆验证结果
那么现在我们就去网页中使用我们获得的密码来进行登录:
登录成功,LAB11 解决。
五、总结与防御建议
总结:
- 本题的核心是基于 Oracle 的条件错误盲注:通过构造会触发报错的分支,把"是否出现内部错误"作为布尔信号来判断条件是否成立。
- 相比 LAB10,这一题不再依赖页面回显 "Welcome back",而是通过服务器错误响应来逐位推导 administrator 的密码长度与内容。
防御建议:
- 使用参数化查询或预编译语句,禁止把 cookie、表单或 URL 参数直接拼接进 SQL。
- 对输入做白名单校验和长度限制,尽量缩小可注入的字符范围。
- 数据库账号遵循最小权限原则,应用只保留必要的查询权限。
- 不要把详细数据库错误直接返回给前端,改为通用错误提示,并在服务端保留审计日志。
- 对密码使用强哈希并加盐存储,避免明文或可逆加密。
- 对异常请求、重复探测和爆破行为设置限速、告警和封禁策略。
- Cookie 和会话应使用安全属性,并避免将未校验的 cookie 值直接用于后端查询。
- 配合 WAF、日志监控和安全告警,及时发现异常注入探测行为。
博客园技术分享 · 请勿用于非法测试