THINKPHP框架审计-利用链 tp5.1.41
字数 1317 2025-10-26 18:21:34

ThinkPHP框架反序列化漏洞审计与利用链分析(TP5.1.41)

一、反序列化漏洞基础知识

1.1 反序列化起点(触发点)

  • __wakeup():使用unserialize时必定触发
  • __destruct():对象被销毁时必定触发
  • __toString():对象被反序列化后又被当做字符串使用时触发

1.2 反序列化跳板(连接点)

  • __toString():对象被当做字符串使用时触发
  • __get():读取不可访问或不存在的属性时被调用
  • __set():给不可访问或不存在的属性赋值时调用

1.3 反序列化终点(执行点)

  • __call():调用不可访问或不存在的方法时被调用
  • call_user_func():PHP代码执行常用函数
  • call_user_func_array():PHP代码执行常用函数

1.4 PHP常用魔术方法

__wakeup()      // 使用unserialize时触发
__sleep()       // 使用serialize时触发
__destruct()    // 对象被销毁时触发
__call()        // 在对象上下文中调用不可访问的方法时触发
__callStatic()  // 在静态上下文中调用不可访问的方法时触发
__get()         // 用于从不可访问的属性读取数据
__set()         // 用于将数据写入不可访问的属性
__isset()       // 在不可访问的属性上调用isset()或empty()触发
__unset()       // 在不可访问的属性上使用unset()时触发
__toString()    // 把类当作字符串使用时触发
__invoke()      // 当脚本尝试将对象调用为函数时触发

二、反序列化漏洞利用条件

2.1 必要条件

  1. 可控的文件:文件使用文件判断类函数操作(phar反序列化)
  2. 可控的变量:变量采用unserialize操作(反序列化)

2.2 实际审计思路

  1. 通过版本判断是否存在反序列化漏洞
  2. 分析利用条件是否满足
  3. 构建完整的利用链

三、ThinkPHP 5.1.41 反序列化利用链实例

3.1 环境搭建与入口点创建

// 创建反序列化入口点
public function unser()
{
    // 漏洞产生点 - 实际审计中发现类似代码即可利用
    unserialize(base64_decode($_GET['id']));
    return "Welcome!";
}

3.2 利用链分析步骤

第一步:寻找魔术方法起点

搜索关键魔术方法:

  • __wakeup(
  • __destruct(

第二步:分析利用链起点

文件路径thinkphp/library/think/process/pipes/Windows.php

public function __destruct()
{
    $this->close();
    $this->removeFiles();  // 关键调用点
}

private function removeFiles()
{
    foreach ($this->files as $filename) {
        if (file_exists($filename)) {
            // 文件操作点,可进一步利用
        }
    }
}

3.3 完整利用链构建

链式调用关系

__destruct() (Windows.php) 
    → removeFiles() 
        → file_exists() 
            → __toString() 触发点
                → 后续跳板方法
                    → 最终代码执行点

四、漏洞利用实战技巧

4.1 任意文件删除漏洞

通过控制$this->files数组,可以实现任意文件删除:

// 构造恶意序列化数据
$evil = new think\process\pipes\Windows();
$evil->files = ['/path/to/important/file.php'];

4.2 远程代码执行(RCE)

通过精心构造的利用链,最终实现代码执行:

  1. 利用文件操作函数触发__toString方法
  2. 通过属性访问触发__get方法
  3. 通过方法调用触发__call方法
  4. 最终到达call_user_func或call_user_func_array实现代码执行

五、防御措施

5.1 安全开发建议

  1. 输入验证:对反序列化操作的用户输入进行严格验证
  2. 白名单机制:限制可反序列化的类
  3. 日志监控:记录反序列化操作日志

5.2 代码层面防护

// 使用白名单限制反序列化类
$allowed_classes = ['SafeClass1', 'SafeClass2'];
$data = unserialize($input, ['allowed_classes' => $allowed_classes]);

六、审计要点总结

6.1 关键搜索关键词

  • unserialize(
  • __destruct
  • __wakeup
  • __toString
  • __get
  • __call
  • call_user_func
  • call_user_func_array

6.2 常见危险函数

  • 文件操作函数:file_exists、unlink等
  • 代码执行函数:eval、assert等
  • 回调函数:call_user_func等

七、学习资源

  • Seebug Paper:https://paper.seebug.org/1040/
  • 相关技术博客和文档

通过系统学习此利用链,安全研究人员可以掌握ThinkPHP框架反序列化漏洞的审计方法和利用技巧,提升代码安全审计能力。

ThinkPHP框架反序列化漏洞审计与利用链分析(TP5.1.41) 一、反序列化漏洞基础知识 1.1 反序列化起点(触发点) __ wakeup() :使用unserialize时必定触发 __ destruct() :对象被销毁时必定触发 __ toString() :对象被反序列化后又被当做字符串使用时触发 1.2 反序列化跳板(连接点) __ toString() :对象被当做字符串使用时触发 __ get() :读取不可访问或不存在的属性时被调用 __ set() :给不可访问或不存在的属性赋值时调用 1.3 反序列化终点(执行点) __ call() :调用不可访问或不存在的方法时被调用 call_ user_ func() :PHP代码执行常用函数 call_ user_ func_ array() :PHP代码执行常用函数 1.4 PHP常用魔术方法 二、反序列化漏洞利用条件 2.1 必要条件 可控的文件 :文件使用文件判断类函数操作(phar反序列化) 可控的变量 :变量采用unserialize操作(反序列化) 2.2 实际审计思路 通过版本判断是否存在反序列化漏洞 分析利用条件是否满足 构建完整的利用链 三、ThinkPHP 5.1.41 反序列化利用链实例 3.1 环境搭建与入口点创建 3.2 利用链分析步骤 第一步:寻找魔术方法起点 搜索关键魔术方法: __wakeup( __destruct( 第二步:分析利用链起点 文件路径 : thinkphp/library/think/process/pipes/Windows.php 3.3 完整利用链构建 链式调用关系 四、漏洞利用实战技巧 4.1 任意文件删除漏洞 通过控制 $this->files 数组,可以实现任意文件删除: 4.2 远程代码执行(RCE) 通过精心构造的利用链,最终实现代码执行: 利用文件操作函数触发__ toString方法 通过属性访问触发__ get方法 通过方法调用触发__ call方法 最终到达call_ user_ func或call_ user_ func_ array实现代码执行 五、防御措施 5.1 安全开发建议 输入验证 :对反序列化操作的用户输入进行严格验证 白名单机制 :限制可反序列化的类 日志监控 :记录反序列化操作日志 5.2 代码层面防护 六、审计要点总结 6.1 关键搜索关键词 unserialize( __destruct __wakeup __toString __get __call call_user_func call_user_func_array 6.2 常见危险函数 文件操作函数:file_ exists、unlink等 代码执行函数:eval、assert等 回调函数:call_ user_ func等 七、学习资源 Seebug Paper:https://paper.seebug.org/1040/ 相关技术博客和文档 通过系统学习此利用链,安全研究人员可以掌握ThinkPHP框架反序列化漏洞的审计方法和利用技巧,提升代码安全审计能力。