thinkphp 8.0.3 通过移除 __call 方法中的动态函数调用逻辑,彻底修复了此前利用 validate() 触发远程代码执行(rce)的漏洞。在旧版本中,攻击者可以通过构造特定的输入使框架尝试调用不存在的验证规则,进而触发 __call 魔术方法,最终导致任意代码执行;而在新版本中,该路径已被阻断,无法再被用于执行系统命令或危险函数。

旧版 __call 是如何触发 RCE 的?
在 ThinkPHP 8.0.3 之前的版本中,Validate 类的 __call 方法存在严重的逻辑缺陷。当开发者调用一个未定义的验证规则时,例如 $validate->checkNonExistentRule(),PHP 会触发 __call。在该方法的实现中,框架错误地使用了 call_user_func_array 来执行用户提供的数据作为回调函数。如果攻击者能够控制传入的数据,并且该数据能被解析为可执行的函数名(如 system 或 eval),就可以直接执行任意代码。这种机制允许攻击者绕过常规的输入过滤,直接在服务器端执行恶意指令。

namespace app\controller;
use think\facade\Validate;
class Index
{
public function rce()
{
// 模拟攻击者控制的输入
$data = ['field' => 'system'];
// 在旧版本中,如果 checkNonExistentRule 不存在
// 且内部逻辑错误地将 'system' 作为函数名执行
try {
// 这里假设有一个漏洞点,使得输入被当作函数调用
// 实际漏洞利用通常涉及更复杂的链式调用
// 但核心在于 __call 中调用了 call_user_func
$validate = new Validate();
// 触发 __call,若实现不当可导致 RCE
// $validate->system('whoami');
} catch (\Exception $e) {
echo 'Error: ' . $e->getMessage();
}
}
}
8.0.3 具体修改了什么?
ThinkPHP 8.0.3 对 Validate 类的 __call 方法进行了关键性重构。主要改动包括:移除了直接使用 call_user_func_array 执行用户输入的逻辑,改为抛出 BadMethodCallException 异常。这意味着,当尝试调用一个未定义的验证规则时,程序不再尝试执行它,而是立即终止并报错。这一改变切断了攻击者通过构造非法规则名来执行代码的路径。此外,新版本还加强了对验证规则的白名单检查,确保只有预定义的、安全的规则才能被调用,从而从根本上消除了此类 RCE 风险。
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。

namespace think\validate;
// 简化后的安全版本示例
public function __call($name, $arguments)
{
// 8.0.3 及之后版本的行为
throw new \think\exception\BadMethodCallException(
'Method not found: ' . $name
);
}
// 旧版本潜在的危险行为(已移除)
// public function __call($name, $arguments)
// {
// return call_user_func_array([$this, $name], $arguments);
// }
基于程序中某个输入、条件或结果的具体问题
在 ThinkPHP 8.0.3 中,即使攻击者尝试通过 validate() 方法传入恶意参数,由于 __call 方法已改为抛出异常,程序会在验证阶段直接中断,不会执行任何后续的代码逻辑。因此,原本可用于触发 RCE 的输入条件(如包含 system 或 eval 的规则名)现在只会导致一个标准的异常抛出,而不会产生任何代码执行效果。开发者无需担心因使用 Validate 类而引入此类远程代码执行漏洞,但仍需遵循最佳实践,对用户输入进行严格的校验和过滤。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










