你有没有遇到过一个你直觉上知道存在漏洞的端点,但你却无法完全理解后端发生了什么或如何利用它?在这篇文章中,我将引导你了解一种技术,它将我的黑盒测试转变为半白盒测试。这种方法导致了多个漏洞的发现,并最终实现了对系统的远程代码执行。
发现端点
在阅读一个JavaScript文件时,我发现了一个名为ExtraServices的端点,于是我打开Burp并在Burp Repeater中请求该端点。然而,该端点返回了404状态码,但与主机始终返回的404略有不同,因此我想这可能是一个不同的主机,于是我开始使用ffuf对该端点进行模糊测试。
使用下面的命令
ffuf -c -w <(cat customwordlist.txt) -u https://company.com/Extraserivce/FUZZ
<()
语法被称为进程替代,它充当一个输入源,程序可以从标准输入读取。我通常在对目标进行模糊测试时使用它,因为它允许我动态调整或修改我的字典列表。
例如,如果你发现一个端点像 api/users/:user:id
,并且你想提取所有用户 ID,而不是创建一个新文件来保存所有用户 ID 然后再进行模糊测试,你可以简单地使用
ffuf -c -w <(seq 1 1337) -u https://company.com/Extraserivce/FUZZapi/users/FUZZ
回到Extraserivce[1]端点,这次对该端点的模糊测试没有得到任何结果,所以我决定暂时放弃。几小时后,我发现之前正常工作的某些端点几乎全部返回了自定义404响应,因此我知道开发者实现了一种功能,使某些端点返回404响应。我知道这一点是因为404响应与上面截图中的不同。所以我抓取了一个之前正常工作的端点,并在路径前面添加了一个反斜杠,例如 /\purl/test
,这时返回了200 OK。因此,我抓取了Extraserivce[2]端点,在其前面也添加了反斜杠,然后重新开始模糊测试
ffuf -c -w <(cat customwordlist.txt) -u https://company.com/\Extraserivce/FUZZ
不久之后,我收到了一个非常有趣的端点,名称为 callAny。
根据端点名称和响应,我认为这个端点接受一个参数,然后在 call_user_func
或 eval
等类似函数中执行它,因此我开始对该端点进行模糊测试,使用了几种GET和POST请求参数,例如:
FUZZ=phpinfo FUZZ=phpinfo()
FUZZ=phpinfo();
等等。我想,也许它直接从POST请求中获取,而不是通过请求参数,使用类似于 php://input
的包装器。
因此,我开始尝试在请求体中注入内容,比如 phpinfo
、<?php phpinfo(); ?>
、ls
等。
什么都没有奏效,我还尝试了一些像SSRF/LFI的方式,但我无法弄清楚后端发生了什么,所以我放弃了。
监控调试模式以了解后端发生了什么
几天后,当我浏览网站并测试其他功能时,收到了下面的错误。这表明开发者在生产环境中开启了调试模式,因为当调试模式开启时,导航到任何返回错误的端点时,它会显示错误详情,因此我可以知道出了什么问题。我迅速再次导航到Extraserivce/[3]callany端点,但为时已晚,开发者在几秒钟后关闭了调试模式。
一个想法在我脑海中闪现,为什么不监控这个端点,如果开发者再次开启调试模式,我就抓取响应呢?于是我决定监控这个端点,检查响应大小是否有变化,如果有变化,就将响应详情发送到我的 Discord 频道。
不久后,我在 Discord 收到了以下三条错误信息:
Warning: Undefined array key “Model” in redacted on lineWarning: 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 的参数,以包含一个特定的模型,然后使用 method 参数来触发包含模型的特定功能。你发现了这个漏洞吗?这是一个 LFI(本地文件包含)漏洞!你可能会想,好吧,你可以包含任何文件,但仍然会得到一个错误,因为你需要一个有效的文件和一个有效的方法,否则服务器将返回 500 状态代码。
除了代码会在包含文件之后触发方法这一事实之外,这在此时并不重要,因为我们已经实现了 LFI。
将 LFI 升级为远程代码执行(RCE)
我喜欢且最快的方法之一是通过 PHP 过滤器链将 LFI 升级为 RCE,更多信息可以参考 Synacktiv 的这篇文章[4]。但由于我们无法控制文件的第一部分,因此我们不能真正使用 PHP 包装器,所以我们需要更加努力。使用经典的方法,如日志注入、PHP 会话注入、读取 proc/self/environ
等,并没有返回任何结果,因此我决定对 web 目录进行模糊测试,寻找可能指示可以写入主机的线索。
我尝试了以下内容:
Model=../FUZZ
我收到了三个结果。阅读 .gitignore
文件时,发现了一些有趣的文件。
特别是 log
和 LOG_Path
目录,因为这些地方可能会记录用户可以控制的内容,比如请求头、参数和路径等。
于是我决定对这两个目录进行模糊测试。然而,幸运的是,在模糊测试时,我忘记包含 log
目录,所以我实际上执行的命令是:
Model=../FUZZ.txt
当我查看响应时,我发现 test.txt
的内容存储了 X-ORIGINAL_URL
端点的整个 HTTP 请求。
于是我请求了 test.txt
文件中的路径,并在请求头中添加了一个 webshell:
T: <?php system($_GET['cmd-old']); ?>
然后执行了 ls
命令作为概念验证。
无 偿 获 取 网 安 资 料:
申明:本账号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关