发现0day并在Mozilla的AWS网络上执行远程代码攻击
原文链接:https://blog.assetnote.io/bug-bounty/2019/03/19/rce-on-mozilla-zero-day-webpagetest/
当Assetnote Continuous Security(CS)监控网络攻击时,它主要使用的工具是WebPageTest。
WebPageTest是一个网站性能测试工具,可让您测试任何给定URL/主机的网络相关指标。
虽然可以通过修改settings.ini
文件来启用基本身份验证,但建议阻止任何匿名访问。Assetnote CS识别的大多数WebPageTest部署都是
未经身份验证的,WebPageTest提供的测试工具阵列可以通过服务器端请求伪造(通常称为SSRF,但对于WebPageTest,它是一个功能)进攻性地用于访问内部资源)。
2017年11月,Assetnote CS在Mozilla的AWS环境中发现了以下资产:
- wpt-vpn.stage.mozaws.net
- wpt1.dev.mozaws.net
这两个都是WebPageTest的实例,不需要身份验证,这是Assetnote CS第一次检测到它的漏洞奖励。与Mathias合作,我们审核了源代码,
在短短几个小时内,我们就能够创建一个导致远程代码执行的攻击链。
虽然在发现时它是0day,但我们与Mozilla和WebPageTest团队合作,将漏洞进行修复处理。
修订本博客文章中列出的错误的提交在2018年1月17日的提交中被推送。
引起我们注意的代码库中的第一件事就是能够通过上传和提取任意Zip文件/www/work/workdone.php
。
此脚本包含一些限制127.0.0.1以外来源访问的逻辑,如下面的代码片段所示:
...
!strcmp($_SERVER['REMOTE_ADDR'], "127.0.0.1")
...
我们稍后再回过头来看看。
在同一个文件中,我们发现了另一个潜在的向量 - 逻辑来上传任意Zip并将其提取到已知位置:
第133 - 136行:/www/work/workdone.php
if (isset($_FILES['file']['tmp_name'])) {
ExtractZipFile($_FILES['file']['tmp_name'], $testPath);
CompressTextFiles($testPath);
}
如果我们可以欺骗我们的IP来自127.0.0.1,似乎我们可以通过这个向量获得代码执行。
但是,由于/www/work/workdone.php
中的第321行,我们发现它并不像我们想象的那么简单:
SecureDir($testPath);
SecureDir函数的逻辑可以在/www/common_lib.inc
中的第2322-239行中找到:
1. /** 1. * Make sure there are no risky files in the given directory and make everything no-execute 1. * 1. * @param mixed $path 1. */ 1. function SecureDir($path) { 1. $files = scandir($path); 1. foreach ($files as $file) { 1. $filepath = "$path/$file"; 1. if (is_file($filepath)) { 1. $parts = pathinfo($file); 1. $ext = strtolower($parts['extension']); 1. if (strpos($ext, 'php') === false && 1. strpos($ext, 'pl') === false && 1. strpos($ext, 'py') === false && 1. strpos($ext, 'cgi') === false && 1. strpos($ext, 'asp') === false && 1. strpos($ext, 'js') === false && 1. strpos($ext, 'rb') === false && 1. strpos($ext, 'htaccess') === false && 1. strpos($ext, 'jar') === false) { 1. @chmod($filepath, 0666); 1. } else { 1. @chmod($filepath, 0666);// just in case the unlink fails for some reason 1. unlink($filepath); 1. } 1. } elseif ($file != '.' && $file != '..' && is_dir($filepath)) { 1. SecureDir($filepath); 1. } 1. } 1. }
由于SecureDir函数在代码流前后之间发生变化,因此存在可利用的条件竞争漏洞,其中提取到Web服务器的PHP文件在被删除之前可以在短时间内访问。
链的第一个预请求者相当容易,因为https://google.com
通过WebPageTest接口运行Traceroute可以获得有效的测试ID
wpt-vpn.stage.mozaws.net:
上图是使用WebPageTest运行traceroute的结果展示
运行traceroute后,WebPageTest将我们重定向到包含后续步骤中使用的测试ID的URL:
http://wpt-vpn.stage.mozaws.net/result/ 171124_GW_9 /
但是我们仍然需要以某种方式欺骗我们127.0.0.1以便访问此脚本中的易受攻击的函数。
我们通过利用以下逻辑来满足这个条件:
第70行:/www/common.inc
1. if (isset($_SERVER["HTTP_FASTLY_CLIENT_IP"]))
1. $_SERVER["REMOTE_ADDR"] = $_SERVER["HTTP_FASTLY_CLIENT_IP"];
这允许我们作为远程用户$_SERVER["REMOTE_ADDR"]
通过发送FASTLY-CLIENT-IP
请求标头来任意设置127.0.0.1
。
将所有这些元素组合在一起,我们能够设置两个Burp Intruder攻击,最终获得代码执行。
一个Burp Intruder攻击用于上传恶意Zip文件,另一个尝试访问提取的PHP文件,而它存在于系统上。我们当时利用条件竞争的解决方案是将Burp Intruder的线程简单地提升到~200。
今天,由于发送请求的速度,使用Turbo Intruder等工具,可以使此漏洞利用更加可靠。
我们能够使用这种技术在Mozilla上实现代码执行,如下面的屏幕截图所示:
上图为wpt-vpn.stage.mozaws.net
的phpinfo()输出
我们首次报告此漏洞的Bugzilla报告现已公开,可在此处查看。该报告包含彻底的复制步骤,对于希望重新创建这些错误的测试人员来说应该足够了。
作为Mozilla的bug赏金计划的一部分,我们获得了500美元。