phar反序列化
前言:看了酒馆师傅的那篇phar反序列化的利用之后,自己就来学习下phar反序列化!
参考文章:https://xz.aliyun.com/t/2958
参考文章:https://paper.seebug.org/680/
参考文章:https://mochazz.github.io/2019/02/02/PHP反序列化入门之phar/#phar介绍
在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作!
不依赖不是说没有,只是相关文件的系统函数底层实现的时候会进行unserialize的操作!
phar文件结构
1.A stub
可以理解为一个标志,格式为xxx<?php xxx; __HALT_COMPILER();?>
,前面内容不限,但必须以__HALT_COMPILER();?>
来结尾,否则phar扩展将无法识别这个文件为phar文件
2.A manifest describing the contents
phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是phar反序列化攻击手法最核心的地方
3.The file contents
被压缩文件的内容。
4.[optional] a signature for verifying Phar integrity (phar file format only)
签名,放在文件末尾,格式如下:
初步了解
注意:要将php.ini中的 phar.readonly 选项设置为Off,否则无法生成phar文件。
然后用php内置的phar类来构建一个文件
<?php class TestObject { } @unlink("phar.phar"); $phar = new Phar("phar.phar"); //后缀名必须为phar $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub $o = new TestObject(); $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); ?>
hex编码工具打开查看,可以看到 meta-data 序列化的内容成功的保存到了文件中
在一些 文件函数 通过 phar:// 伪协议解析phar文件时都会将meta-data反序列化
受影响的函数有
fileatime filectime filemtime file_exists file_get_contents file_put_contents file filegroup fopen fileinode fileowner fileperms is_dir is_file is_link is_executable is_readable is_writeable is_wirtble parse_ini_file copy unlink stat readfile info_file
已经序列化的内容已经保存在了phar.phar中,我们用受影响的函数进行试验,去触发反序列化
<?php class TestObject { public function __destruct() { echo 'Destruct called'; } } $filename = 'phar://phar.phar/test.txt'; //test.txt是保存在phar包中的文件条目 file_exists($filename); //受影响的file_exists函数 ?>
结果内容如下:
可以看到先触发了反序列化 输出了test内容,然后还会执行当前TestObject类中的析构函数,如果当前没有写TestObject类的话,单纯执行反序列化只会输出test内容!
当文件系统函数的参数可控时,我们可以在 不调用unserialize()的情况下 进行 反序列化操作 ,一些之前看起来"人畜无害"的函数也变得"暗藏杀机",极大的拓展了攻击面 !
PHP底层phar解析数据处理过程
处理代码如下:
int phar_parse_metadata(char **buffer, zval *metadata, uint32_t zip_metadata_len){ php_unserialize_data_t var_hash; if (zip_metadata_len) { const unsigned char *p; unsigned char *p_buff = (unsigned char *)estrndup(*buffer, zip_metadata_len); p = p_buff; ZVAL_NULL(metadata); PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(metadata, &p, p + zip_metadata_len, &var_hash)) { //这里是最重要的,如果metadata存在的话 就会帮我们进行反序列化的操作,if语句后面就是对前面生成的数据的内存清除 efree(p_buff); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); zval_ptr_dtor(metadata); ZVAL_UNDEF(metadata); return FAILURE; } efree(p_buff); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } }
unserialize 的定义为:若被解序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup() 成员函数(如果存在的话)
所以先前定义的 TestObject 类,当有数据被反序列化了之后就会被重新构造为TestObject类的对象,并且还会有属于自己的属性!
phar包的伪装
phar文件还可以伪装后缀名,首先要知道的phar文件唯一的标识符__HALT_COMPILER();?>
,只要不影响标识符,那么我们就可以通过 添加任意的文件头 + 修改后缀名的方式 来将phar文件伪装成其他格式的文件
<?php class TestObject { } @unlink("phar.phar"); $phar = new Phar("phar.phar"); $phar->startBuffering(); $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头 $o = new TestObject(); $phar->setMetadata($o); //将自定义meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); ?>
生成的文件为如下:
采用这种方法可以绕过很大一部分上传检测。
phar反序列化实际应用
- phar文件要能够上传到服务器端
- 要有可用的魔术方法作为"跳板"
- 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤
拿一道ctf的题目来进行学习:
第一题:
<?php if(isset($_GET['filename'])){ $filename = $_GET['filename']; class MyClass{ var $Output = 'echo "hahaha"'; function __destruct() { // TODO: Implement __destruct() method. eval($this->Output); } } file_exists($filename); }else{ highlight_file(__FILE__); }
我们可以通过上面生成phar包,其中meta-data
部分是 存储了MyClass实例化的对象值,然后通过$_GET['filename']
,进行 file_exists 从而触发反序列化来覆盖 $Output 变量,最后导致eval($this->Output);
命令执行!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY