背景介绍
你是否遇到过明知一个端点可能很容易受到攻击,但你又不太了解后端究竟发生了什么以及该如何利用它们?
那么在本文中,将指导你完成一种将黑盒测试转变为半白盒测试的技术。这种方法发现了多个漏洞,并最终实现了系统上的RCE(远程代码执行)。
发现端点
在读取其中一个 JS 文件时,白帽小哥发现了一个名为 ExtraServices 的端点。
那么果断打开 Burp 并将请求发送至Repeater中,端点返回了 404 代码,但却与主机始终返回的 404 代码略有不同,因此猜测这可能是一个不同的主机,于是立即使用 FFUF 对端点进行Fuzz,运行:
ffuf -c -w <(cat customwordlist.txt ) -u https://company.com/Extraserivce/FUZZ
<()语法
(也被称为进程替换),这将充当程序可以从 stdin 读取输入。
该语法可以动态调整或修改你的‘爆破’字典列表。
例如,如果你找到像api/users/:user:id
的端点,想要转储所有用户 ID,那么就无需创建一个新文件来专门保存所有用户 ID,这样就可以轻松的使用它进行Fuzz。
ffuf -c -w <(seq 1 1337) -u https://company.com/api/users/FUZZ
回到Extraserivce端点,模糊测试该端点并没有收到任何有用的结果。
几个小时后,白帽小哥发现之前工作的一些端点几乎全部返回了自定义 404 的响应,因此可以知道开发人员实现了一项为某些端点返回自定义 404 响应的功能。
由于知道 404 响应与上面的截图有所不同,因此白帽小哥抓住了之前正在工作的其中一个端点,并在路径开始前添加了一个反斜杠 \
,
类似 /\purl/test
顺利收到返回的 200 OK 响应。
通过在 Extraserivce 端点之前添加了一个反斜杠,再次进行Fuzz。
ffuf -c -w <(cat customwordlist.txt ) -u https://company.com/\Extraserivce/FUZZ
白帽小哥很快便收到一个非常有趣的端点,它有一个非常有趣的名称callAny。
根据端点名称和响应结果,白帽小哥认为该端点正在获取一个参数,然后在 call_user_func
或 eval
或执行代码的任何类似函数内执行它,因此白帽小哥开始使用几个值对 GET、POST 请求参数的端点进行Fuzz,比如:
FUZZ=phpinfo
FUZZ=phpinfo()
FUZZ=phpinfo();
还有更多人认为也许它可以直接从 POST 请求中获取,而不用使用类似 php://input wrapper
的请求参数。
因此白帽小哥开始尝试phpinfo <?php phpinfo();
、?> ls
之类的注入。
尝试了诸如 SSRF和LFI 之类的测试后,由于无法真正弄清楚后端究竟发生了什么,因此白帽小哥决定放弃。
监控调试模式
几天后,在浏览网站并测试其它功能时,白帽小哥收到了以下错误,
这表明开发人员在生产过程中开启了调试模式,因为如果导航到任何返回错误的端点,则会启用调试模式,它将显示错误详细信息,因此白帽小哥将能够知道出了什么问题。
于是白帽小哥很快再次导航到Extraserivce/callany
端点,但还是晚了一步,开发人员在几秒钟后关闭了调试模式。
但是白帽小哥脑海中闪现出一个想法,为什么不监视该端点并在开发人员再次打开调试模式时获取响应?
于是白帽小哥决定监视该端点并检查响应大小是否不同,它会将响应详细信息发送到我的白帽小哥的Discord频道。
如果想了解如何监控目标,可以自行观看以下视频:
https://www.youtube.com/watch?v=wP3n1JnqtMU
不久之后,白帽小哥便在Discord收到了 3 个错误信息。
Warning: Undefined array key “Model” in redacted on line
Warning: Undefined array key “Method” in redacted on line
Warning: include_once(Models/): Failed to open stream: No such file or directory in redacted on line
现在终于知道发生了什么,开发人员采用名为 Model 的参数来包含特定模型,然后使用方法参数来触发所包含模型上的特定函数。
你发现漏洞了吗?这是一个典型的LFI漏洞!!!
你可能认为可以包含任何文件,但仍然会收到错误,因为你需要有效的文件和有效的方法,否则服务器将会返回 500 错误。
成功实现了LFI!
将LFI升级为RCE
将 LFI 升级为 RCE 的方法之一是通过来自https://www.synacktiv.com/publications/php-filters-chain-what-is-it-and-how-to-use的-it.html 的 php 过滤链,但由于我们无法控制文件的第一部分,因此我们无法真正使用 php wrapper。
使用经典方法,例如日志中毒 php 会话注入、读取 proc/self/environ 等并没能返回任何结果,因此白帽小哥决定对 Web 目录进行Fuzz,寻找可能写入主机方法的有用线索。
Model=../FUZZ
然后白帽小哥又收到了 3 个结果,通过阅读 .gitignore 发现了一些有趣的文件。
特别是 log 和 LOG_Path 目录,因为它可能会记录用户可以控制的一些内容,例如 headers/params/path 等。
所以白帽小哥决定对这两个目录进行Fuzz,幸运的是,在Fuzz时白帽小哥忘记了包含日志目录。
正常Fuzz应该是:Model=../log/FUZZ.txt
但小哥输入的是Model= ../FUZZ.txt
当查看响应时,发现 test.txt 的内容存储了 X-ORIGINAL_URL 端点的完整 http 请求。
通过请求 test.txt 文件中的路径并在标头中增加 webshell:
T: <?php system($_GET[‘cmd-old’]); ?>
从而执行 ls 命令作为PoC:
顺利将LFI提升为RCE!
以上内容由骨哥翻译并整理。
原文:https://medium.com/@0xold/15k-rce-through-monitoring-debug-mode-4f474d8549d5