当Assetnote持续安全性(CS)监视您的攻击面时,它查找的内容之一就是WebPageTest的实例。WebPageTest是网站性能测试工具,可让您测试任何给定URL /主机的网络相关指标。
尽管可以通过修改settings.ini文件来启用基本身份验证,但建议进行基本身份验证以防止任何匿名访问。Assetnote CS标志的大多数WebPageTest部署未经身份验证,并且WebPageTest提供的一系列测试工具可用于服务器端请求伪造(通常称为SSRF,但对于WebPageTest而言,是一种功能),可令人反感)。
以前在Assetnote CS在Mozilla的AWS环境中发现了以下资产:
这两个都是WebPageTest的实例,不需要身份验证,这是Assetnote CS首次检测到它是为了赏金。通过与Mathias的合作,我们审核了源代码,并且在短短的几个小时内,我们就能够创建一条导致远程执行代码的攻击链。
代码库中引起我们注意的第一件事是能够通过上载和提取任意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-2347行中找到:
/**
* Make sure there are no risky files in the given directory and make everything no-execute
*
* @param mixed $path
*/
function SecureDir($path) {
$files = scandir($path);
foreach ($files as $file) {
$filepath = "$path/$file";
if (is_file($filepath)) {
$parts = pathinfo($file);
$ext = strtolower($parts['extension']);
if (strpos($ext, 'php') === false &&
strpos($ext, 'pl') === false &&
strpos($ext, 'py') === false &&
strpos($ext, 'cgi') === false &&
strpos($ext, 'asp') === false &&
strpos($ext, 'js') === false &&
strpos($ext, 'rb') === false &&
strpos($ext, 'htaccess') === false &&
strpos($ext, 'jar') === false) {
@chmod($filepath, 0666);
} else {
@chmod($filepath, 0666); // just in case the unlink fails for some reason
unlink($filepath);
}
} elseif ($file != '.' && $file != '..' && is_dir($filepath)) {
SecureDir($filepath);
}
}
}
由于SecureDir函数是在代码流的稍后阶段发生的,因此存在一种可利用的竞争条件,在该条件下,被提取到Web服务器的PHP文件在被删除之前可在短时间内访问。
链中的第一个前提条件非常简单,因为https://google.com通过在WebPageTest接口上运行Traceroute可以获取有效的测试ID wpt-.stage.mozaws.net:
使用WebPageTest运行traceroute
运行traceroute之后,WebPageTest将我们重定向到一个URL,该URL包含后面步骤中使用的测试ID:
但是我们仍然需要以某种方式欺骗我们127.0.0.1,以便访问此脚本中易受攻击的功能。
通过使用以下逻辑,我们能够满足此条件:
第70行:/www/common.inc
if (isset($_SERVER["HTTP_FASTLY_CLIENT_IP"]))
$_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-.stage.mozaws.net的phpinfo()输出
关注:Hunter网络安全 获取更多资讯
网站:bbs.kylzrv.com
CTF团队:Hunter网络安全
文章:Shubham Shah
排版:Hunter-匿名者