ThinkPHP5.0.x反序列化利用链
字数 1591 2025-08-26 22:11:51
ThinkPHP5.0.x反序列化利用链分析
漏洞概述
本文详细分析ThinkPHP5.0.x版本中的反序列化漏洞利用链。该漏洞通过精心构造的反序列化数据,可以实现任意文件写入,最终获取Webshell权限。
环境要求
- PHP版本:5.6
- 操作系统:Linux
- ThinkPHP版本:5.0.24
漏洞测试代码
<?php
namespace app\index\controller;
class Index {
public function index() {
$c = unserialize($_GET['c']);
var_dump($c);
return 'Welcome to thinkphp5.0.24';
}
}
POP链分析
入口点:think\process\pipes::__destruct
- 通过
__destruct方法里调用的removeFiles方法 - 利用
file_exists函数触发任意类的__toString方法 - 选择
think\Model类来触发(需使用其子类如think\Model\Pivot)
__toString触发点
- 在ThinkPHP5.1.X中,通常在调用
think\Model::toArray()时触发think\Request::__call() - 但在5.0.X中,
think\Request::__call()写法不同,成员变量不可控
替代__call方法选择
选择think\console\Output类:
- 其
__call方法最终调用$this->handle->write() $this->handle可控,需要找到具有可利用write方法的类
文件写入点选择
将think\console\Output类的handler属性设置为think\session\driver\Memcached类对象:
think\session\driver\Memcached::write()中调用set方法think\cache\driver\File::set()方法可以写文件
文件写入细节
$filename的前一部分$this->options['path']可控$value在think\console\Output::writeln()中固定为true$this->setTagItem($filename)中又调用set方法写文件- 此时
$value为部分可控的$filename - 可利用PHP伪协议写shell
- 此时
示例payload:
php://filter/write=string.rot13/resource=<?cuc @riny($_TRG[_]);?>
(访问webshell时需将文件名中的?URL编码为%3f)
toArray中的__call触发
通过$value->getAttr()触发think\console\Output::__call():
$value必须是think\console\Output类对象- 在
$this->getRelationData($modelRelation)中被赋值 $modelRelation = $this->$relation(),选择返回结果简单可控的getError方法
getRelationData方法分析
$this->parent需为think\console\Output类对象think\model\Relation类的isSelfRelation、getModel方法返回值可控- 使用
think\model\Relation的子类完成利用
替代利用方式
如果网站不允许写文件,可以:
- 修改payload创建0755权限目录(利用
think\cache\driver\File::getCacheKey()中的mkdir函数) - 然后往该目录写文件
防御建议
- 避免反序列化用户可控数据
- 升级到最新安全版本
- 对文件操作进行严格权限控制
- 禁用危险PHP函数和协议
总结
该漏洞利用链通过精心构造的反序列化数据,利用多个类的魔术方法和特性,最终实现任意文件写入。理解该漏洞有助于开发者更好地防范类似安全问题。