thinkphp反序列化漏洞需切断用户输入到unserialize的通路,通过代码层替换为json_decode、配置层升级至6.3+并禁用高危类、运行时启用unserialize_callback_func白名单及日志监控实现三重防护。

ThinkPHP反序列化漏洞不能靠“打补丁式修复”解决,核心在于切断用户可控输入到反序列化调用的通路,并限制反序列化行为本身。框架版本升级只是基础动作,真正有效的修复必须结合代码层、配置层和运行时三重控制。
明确反序列化入口点并移除危险调用
所有修复工作的起点是定位 unserialize() 的实际使用位置。常见入口包括:
- 控制器中直接调用
unserialize($_GET['data'])或unserialize(file_get_contents('php://input')) - 缓存驱动(如
think\cache\driver\Memcached)在构造或销毁过程中隐式触发 - 路由解析、会话处理、日志写入等扩展逻辑中未校验的反序列化操作
一旦确认入口,应立即替换为安全替代方案:
- 用 json_decode() 替代 unserialize(),前提是数据源可控且不依赖对象特性
- 若必须传输结构化对象,改用 igbinary 或 msgpack 等二进制格式,并禁用 PHP 原生反序列化
- 对无法替换的旧逻辑,增加白名单校验:仅允许反序列化已知、无魔术方法风险的简单数据类
升级框架并禁用高危类自动加载
ThinkPHP 6.0.13 及更早版本存在多条 POP 链(如 ResourceRegister → DbManager → Memcached → Pivot),官方已在 6.1+ 版本中重构缓存与模型模块,移除了关键链路中的危险调用。修复建议:
- 生产环境必须升级至 ThinkPHP 6.3.x 或更高稳定版,避免使用已 EOL 的 6.0.x 分支
- 在
composer.json中锁定框架版本,禁止自动升级到未经安全验证的小版本 - 通过
composer dump-autoload --no-dev减少自动加载类数量,降低攻击面 - 在
app/provider.php中移除非必要服务提供者(如废弃的think\cache\driver\Apc)
运行时加固:启用 unserialize_callback_func 和类过滤
即使代码层做了清理,运行时防护仍是最后一道防线。在 public/index.php 顶部添加:
ini_set('unserialize_callback_func', 'my_unserialize_callback');
function my_unserialize_callback($class) {
$whitelist = ['think\model\Json', 'app\common\Dto'];
if (!in_array($class, $whitelist)) {
throw new Exception('Unserialization of class ' . $class . ' is forbidden');
}
}
同时,在 PHP 配置中启用 session.serialize_handler = php_serialize,避免 session 数据被恶意构造为反序列化载荷。
日志与监控:让异常反序列化行为可见
很多攻击在首次利用时就会触发 __wakeup() 中的非法操作并报错。应在应用层统一捕获反序列化异常:
- 重写
think\ExceptionHandle,对包含unserialize、__wakeup、__destruct的错误堆栈做告警 - 在 Nginx/Apache 日志中记录含
unserialize、phar://、php://input的请求参数 - 使用开源工具如 php-malware-finder 定期扫描项目中潜在的危险模式
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











