前记
上周,在美国的BlackHat会议上宣布了一种针对PHP应用程序的新漏洞利用方式。你可以在这篇文章中了解到它。
概要
来自Secarma的安全研究员Sam Thomas发现了一种新的漏洞利用方式,可以在不使用php函数unserialize()
的前提下,引起严重的php对象注入漏洞。
这个新的攻击方式被他公开在了美国的BlackHat会议演讲上,演讲主题为:”不为人所知的php反序列化漏洞”。它可以使攻击者将相关漏洞的严重程度升级为远程代码执行。我们在RIPS代码分析引擎中添加了对这种新型攻击的检测。
流包装
大多数PHP文件操作允许使用各种URL协议去访问文件路径:如data://
,zlib://
或php://
。其中一些通常用于利用远程文件包含漏洞,攻击者可以利用它们控制文件包含的完整路径。例如,用于网站源代码的读取或者是用于代码执行:
include('php://filter/convert.base64-encode/resource=index.php');
include('data://text/plain;base64,cGhwaW5mbygpCg==');
Phar元数据
但到目前为止,没有人关注phar://
。Phar(PHP Archive)文件的有趣之处在于它包含序列化格式的元数据。让我们创建一个Phar文件,并添加一个包含一些数据的对象作为元数据:
// create new Phar
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); ? >');
// add object of any class as meta data
class AnyClass {}
$object = new AnyClass;
$object->data = 'rips';
$phar->setMetadata($object);
$phar->stopBuffering();
我们新创建的test.phar
文件现在具有以下内容。我们可以看到我们的对象存储为序列化字符串。
PHP对象注入
如果现在通过phar://
对我们现有的Phar文件进行文件操作,则其序列化元数据将被反序列化。这意味着我们在元数据中注入的对象将被加载到应用程序中。如果此应用程序具有已命名的类AnyClass
,并且具有魔术函数__destruct()
或__wakeup()
,则会自动调用这些方法。这意味着我们可以在代码库中触发任何析构函数或唤醒方法。
更糟糕的是,如果这些魔法函数对我们注入的数据进行操作,那么这可能会导致进一步的漏洞:
class AnyClass {
function __destruct() {
echo $this->data;
}
}
// output: rips
include('phar://test.phar');
漏洞利用
首先,攻击者必须能够在目标Web服务器上植入精心制作的Phar文件。而Sam Thomas发现了一些关于如何将Phar文件隐藏到JPG中的好技巧,因此常见的图像上传功能已足够。
到目前为止,攻击者如果可以控制诸如include()
,fopen()
,file_get_contents()
,file()
等文件操作的函数,则可以造成严重的漏洞。因此,通常需要在这些函数使用前验证用户的输入。
但是,phar://
在任何文件操作中都会触发反序列化。例如用file_exists()
简单地检查文件的存在。这些函数一直被认为不太可能引起安全问题,所以一直被保护的不够好。
使用RIPS进行自动检测
通过RIPS的污点分析,我们可以在PHP文件操作中自动检测用户输入的未经过滤或验证的信息。这样,我们即可检测文件删除、泄露、写入、创建、包含(等等)漏洞。
此外,RIPS的上下文敏感字符串分析使我们能够精确评估文件路径是完全还是仅部分能被攻击者控制,以及是否可以注入phar://
。最后,RIPS能够扫描可能导致对象注入漏洞的较短的攻击链。我们在RIPS代码分析器中添加了一个名为Phar Deserialization
的新漏洞类型,以检测这种新类型的代码风险。