0x00 伪协议

PHP伪协议大致有如下几种

file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流

伪协议了解的较多的是包含文件,利用php://、data://、file://、zlib://等协议特性,包含恶意代码文件,或读取,或下载。

本次需要了解的是phar伪协议,PHP文档中解释为PHP归档,可解压缩包,也可包含文件,读取文件等操作。而在2018年BlackHat USA大会上,来自Secarma的安全研究员Sam Thomas公布的针对PHP新型攻击技术,利用phar流包装在不使用unserialize函数的情况下触发反序列化漏洞。

0x01 phar文件格式

phar文件格式大致有3-4个部分

  • a stub

    ​ stub基本结构:,前面内容不限,但是必须以__HALT_COMPILER();?>结尾,否则phar扩展无法将此文件识别为phar文件。

  • manifest describing the contents

    ​ phar文件的压缩信息,其中meta-data部分的信息会以序列化的形式存储,而此为漏洞触发关键点。(有序列化就有反序列化)

    image-20201027171209011

  • the file contents

    ​ 被压缩的文件内容,无特殊要求下,此文件内容可任意修改。

  • a signature for verifying Phar integrity

    ​ 签名格式。

根据文件格式构造一个phar文件,php内置phar类处理相关操作。

demo.php

class TestObject {
}

@unlink("phar.phar");

$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

$o = new TestObject();

$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

访问demo文件后,会在当前目录生成一个phar.phar文件

image-20201027180943383

可以看见文件格式,中间部分是以序列化格式存储

image-20201027181105728

0x02 漏洞利用

参考:https://blog.zsxsoft.com/post/38

https://xz.aliyun.com/t/2715