Phar反序列化漏洞

前言

通常我们在利用反序列化漏洞的时候,只能将序列化后的字符串传入 unserialize() ,随着代码安全性越来越高,利用难度也越来越大。但是利用 phar 文件会以反序列化的形式存储用户自定义的 meta-data 这一特征,拓展了 php 反序列化漏洞的攻击面。该方法在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合 phar:// 协议,可以不依赖 unserialize() 直接进行反序列化操作。

Phar反序列化漏洞的原理

什么是Phar?

Phar("Php ARchive") 是PHP 里类似于 JAR 的一种打包文件,在 PHP 5.3 或更高版本中默认开启,这个特征使得 PHP 也可以像 Java 一样方便地实现应用程序打包和组件化。一个应用程序可以打包一个Phar 包, 直接放到 PHP-FPM 中运行。

PHP内置的流包装器

php 通过用户定义和内置的“流包装器”实现复杂的文件处理功能。内置包装器可用于文件系统函数。如(fopen(),copy(),file_exists()和filesize())。 phar://就是一种内置的流包装器

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支持的协议和包装器

Phar文件结构

  1. a stub

可以理解为一个标志,格式为xxx<?php xxx; __HALT_COMPILER();?>,前面的xxx内容不限,但必须是以__HALT_COMPILER();?>来结尾,否则phar扩展将无法识别这个文件为phar文件。

  1. a manifest describing the contents、

Phar文件中被压缩的文件的一些信息,其中Meta-data部分的信息会以序列化的形式储存,这里就是漏洞利用的关键点

  1. the file contents

被压缩的文件内容,在没有特殊要求的情况下,这个被压缩的文件内容可以随便写的,因为我们利用这个漏洞主要是为了触发它的反序列化

  1. a signature for verifying Phar integrity

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

测试

根据文件结构我们来自己构建一个phar文件,php内置了一个Phar类来处理相关操作。

注意:要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件。

phar_demo.php

<?php
    class TestObject {
    }
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new TestObject();
    $o->data = 'seizer';
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

运行代码后,会生成一个phar.phar的文件在当前目录下

      Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 	
00000000: 3C 3F 70 68 70 20 5F 5F 48 41 4C 54 5F 43 4F 4D    <?php.__HALT_COM
00000010: 50 49 4C 45 52 28 29 3B 20 3F 3E 0D 0A 64 00 00    PILER();.?>..d..
00000020: 00 01 00 00 00 11 00 00 00 01 00 00 00 00 00 2E    ................
00000030: 00 00 00 4F 3A 31 30 3A 22 54 65 73 74 4F 62 6A    ...O:10:"TestObj
00000040: 65 63 74 22 3A 31 3A 7B 73 3A 34 3A 22 64 61 74    ect":1:{s:4:"dat
00000050: 61 22 3B 73 3A 36 3A 22 73 65 69 7A 65 72 22 3B    a";s:6:"seizer";
00000060: 7D 08 00 00 00 74 65 73 74 2E 74 78 74 04 00 00    }....test.txt...
00000070: 00 CE E8 66 61 04 00 00 00 0C 7E 7F D8 B6 01 00    .Nhfa.....~.X6..
00000080: 00 00 00 00 00 74 65 73 74 A6 98 F8 F3 51 ED C0    .....test&.xsQm@
00000090: FE 94 7A E7 FC 1A 77 1D 83 52 78 FD B0 02 00 00    ~.zg|.w..Rx}0...
000000a0: 00 47 42 4D 42                                    			 .GBMB

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

phar_fan.php

<?php
class TestObject{
    function __destruct()
    {
        echo $this -> data;   // TODO: Implement __destruct() method.
    }
}
include($_GET['phar']);
?>

成功触发反序列化

image-20211013221751010

参考文章:

利用 phar 拓展 php 反序列化漏洞攻击面

phar反序列化

Phar反序列化总结

posted @ 2023-01-08 23:14  seizer-zyx  阅读(109)  评论(0编辑  收藏  举报