因此,当我和朋友一起测试网站时,我们发现了一个如下的 API 端点:
` https://api.test.com/users/public?page=1&search=bug_vs_me`
在前端,我们可以选择搜索用户。如果我搜索bug_vs_me
,它会显示我的账户、我的头像和公开用户信息——没有任何敏感信息。但如果我搜索`'bug_vs_me`
(使用'
),它不会显示任何结果,这意味着它会破坏后端的 SQL 查询。但在前端,没有显示任何错误,所以一些漏洞赏金猎人懒得去检查为什么bug_vs_me
有结果有结果却'bug_vs_me
没有结果。
因此我检查了我的 Burp 请求历史记录并手动开始测试此 SQL。
☝️ 看上图,我搜索了“deepak”,并得到了结果。
☝️ 见上图,我搜索了“OR Testing1337”,但没有得到任何结果 + SQL 错误,一些漏洞猎人不会手动检查 API 请求。
因此,我们确认存在 SQL 注入,并且后端是 PostgreSQL — — 但是等等……
Cloudflare WAF 非常严格。我尝试过 SQLMAP 和其他工具来提取数据,但都因为 Cloudflare WAF 而失败了。我擅长绕过任何 WAF,但对于 XSS 攻击(而不是 SQL 注入)我非常了解,因为 SQL 注入需要我们使用`IF`, `OR`, `AND`
等来构造查询,而 WAF 会阻止我所有的有效载荷,例如`’OR’1'=’1`
→ BLOCKED。其他有效载荷也是如此。
所以我花了3个多小时试图绕过它。以下是我如何绕过WAF,并仅使用公开用户名提取任何用户的电子邮件。
这个SQL注入是Boolean-Based Blind SQL Injection
,所以我尝试阅读PostgreSQL
文档,发现我们可以使用` ILIKE
`,它用于不区分大小写的模式匹配。
所以我设计了这个查询:/users/public?page=1&search={}'+Or+publicusername+ILIKE+'deepak
瞧,这个查询给了我一个结果,而且我注意到还有一个被屏蔽的邮箱地址。那么为什么不提取邮箱地址呢?所以我使用了下面的查询:
这里请注意:` publicusername
` 列存储公共用户名 slug,而 ` username
` 列存储不公开的用户电子邮件。
所以上面的 SQL 查询基本上是这样的:它会检查 SQL 数据库中是否存在任何 ` publicusername
ILIKE` deepak
,以及 ` publicusername
` 是否包含 ` username
ILIKE [email protected]`。如果为 true,则会看到数据。如果为 false,则不会看到任何结果。
因此我向团队报告,使用每个单词逐个分析,我们可以提取完整的电子邮件,如下所示:
上面,我搜索了 if ` username
` (email) is ` dee
` →> true
,得到了结果。
上面,我搜索了 if ` username
` (email) is ` deex
` →> false
,但没有得到结果。
同样的方式,我们可以提取完整的电子邮件,然后我写了一份详细的报告并提交了。
— -
### 但是等等 — — 看看项目团队的回应:
经过一番反复讨论,他们仍然不同意这是 SQL 注入!所以我为他们编写了一个脚本,只需输入用户的公开用户名,20 秒内就能提取完整的电子邮件。
脚本如下:
# 脚本流程说明
1.输入收集——脚本提示用户输入一个` public_username
`(例如` john123
`),即需要提取其电子邮件的目标用户。
2. 初始化- 将 `email_prefix` 初始化为空字符串。- 定义包含电子邮件中可能出现的字符的 `charset`:`abcdefghijklmnopqrstuvwxyz0123456789@._`
3. 开始提取循环- 进入“while True”循环,一次强制提取电子邮件中的一个字符。
4. 字符测试- 对于 `charset` 中的每个字符 `c`:- 将 `c` 附加到当前 `email_prefix` 以创建一个新的猜测(“attempt”)。- 使用以下方式构造 SQL 注入有效负载:```' OR publicusername ILIKE '<public_username>' AND username ILIKE '<attempt>'```- 发送 GET 请求至:```https://api.test.com/users/public?page=1&search= <payload>```
5. 响应分析- 检查响应是否:— HTTP 状态码为 `200`— JSON 包含 `”status”: “success”— `”public” 列表不为空— 如果所有条件均满足,则猜测的前缀有效。字符 `c` 将被添加到 `email_prefix` 中,并继续执行。
6. 终止- 如果在一次迭代中没有来自“charset”的字符匹配(没有进展),则循环中断,假设已提取完整的电子邮件。
7. 最终输出- 打印完全提取的电子邮件前缀:
感谢immunefi调解小组帮助解决冲突
感谢immunefi mediavtion团队
最后…
原文始发于微信公众号(安全狗的自我修养):如果有严格的 WAF,如何升级 SQL 注入?
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论