白帽故事 · 2024年9月14日 0

【赏金15000美元】通过监控调试模式实现 RCE

背景介绍

你是否遇到过明知一个端点可能很容易受到攻击,但你又不太了解后端究竟发生了什么以及该如何利用它们?

那么在本文中,将指导你完成一种将黑盒测试转变为半白盒测试的技术。这种方法发现了多个漏洞,并最终实现了系统上的RCE(远程代码执行)。

发现端点

在读取其中一个 JS 文件时,白帽小哥发现了一个名为 ExtraServices 的端点。

那么果断打开 Burp 并将请求发送至Repeater中,端点返回了 404 代码,但却与主机始终返回的 404 代码略有不同,因此猜测这可能是一个不同的主机,于是立即使用 FFUF 对端点进行Fuzz,运行:

ffuf -c -w <(cat customwordlist.txt ) -u https://company.com/Extraserivce/FUZZ

file

<()语法(也被称为进程替换),这将充当程序可以从 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

file

根据端点名称和响应结果,白帽小哥认为该端点正在获取一个参数,然后在 call_user_funceval 或执行代码的任何类似函数内执行它,因此白帽小哥开始使用几个值对 GET、POST 请求参数的端点进行Fuzz,比如:

FUZZ=phpinfo

FUZZ=phpinfo()

FUZZ=phpinfo();

还有更多人认为也许它可以直接从 POST 请求中获取,而不用使用类似 php://input wrapper 的请求参数。

因此白帽小哥开始尝试phpinfo <?php phpinfo();?> ls 之类的注入。

file

尝试了诸如 SSRF和LFI 之类的测试后,由于无法真正弄清楚后端究竟发生了什么,因此白帽小哥决定放弃。

监控调试模式

几天后,在浏览网站并测试其它功能时,白帽小哥收到了以下错误,

file

这表明开发人员在生产过程中开启了调试模式,因为如果导航到任何返回错误的端点,则会启用调试模式,它将显示错误详细信息,因此白帽小哥将能够知道出了什么问题。

于是白帽小哥很快再次导航到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 错误。

file

file

成功实现了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

file

然后白帽小哥又收到了 3 个结果,通过阅读 .gitignore 发现了一些有趣的文件。

file

特别是 log 和 LOG_Path 目录,因为它可能会记录用户可以控制的一些内容,例如 headers/params/path 等。

所以白帽小哥决定对这两个目录进行Fuzz,幸运的是,在Fuzz时白帽小哥忘记了包含日志目录。

正常Fuzz应该是:Model=../log/FUZZ.txt
但小哥输入的是Model= ../FUZZ.txt

当查看响应时,发现 test.txt 的内容存储了 X-ORIGINAL_URL 端点的完整 http 请求。

file

通过请求 test.txt 文件中的路径并在标头中增加 webshell:

T: <?php system($_GET[‘cmd-old’]); ?>

从而执行 ls 命令作为PoC:

file

顺利将LFI提升为RCE!

以上内容由骨哥翻译并整理。

原文:https://medium.com/@0xold/15k-rce-through-monitoring-debug-mode-4f474d8549d5