应禁用unserialize()、实施类名白名单、加固__destruct方法、启用php内置防护及部署waf规则。具体包括替换为json_decode、限定允许类、移除危险函数调用、配置php.ini限制及编写正则拦截序列化特征。

如果PHP应用程序在反序列化用户可控输入时未做严格校验,攻击者可通过构造恶意序列化字符串,利用__destruct魔术方法触发任意代码执行。以下是针对该攻击路径的多种防御措施:
一、禁用危险的反序列化入口点
最直接有效的手段是彻底移除对unserialize()函数的不安全调用,尤其避免将$_GET、$_POST、$_COOKIE等用户输入直接传入该函数。应优先采用类型安全的数据交换格式替代PHP原生序列化。
1、定位所有unserialize(调用位置,使用grep -r "unserialize(" ./app/命令扫描项目目录。
2、将存在风险的unserialize($_GET['data'])替换为json_decode($_GET['data'], true),并确保JSON_THROW_ON_ERROR标志启用。
3、若必须保留序列化机制,仅允许从可信内部来源(如预定义配置文件、服务间固定通道)读取数据,且路径需硬编码或白名单校验。
二、实施类名白名单过滤
在调用unserialize()前,预先拦截非法类名,防止攻击者实例化恶意构造的类。该策略可阻断绝大多数基于__destruct的链式调用。
1、定义允许反序列化的类名数组,例如$allowed_classes = ['UserSession', 'CacheItem', 'ConfigSnapshot'];
2、使用unserialize($input, ['allowed_classes' => $allowed_classes])(PHP 7.4+),确保仅指定类可被重建。
3、若运行环境低于PHP 7.4,改用正则匹配序列化字符串头:检查是否以O:[0-9]+:"(UserSession|CacheItem|ConfigSnapshot)"开头,否则拒绝处理。
三、重写__destruct逻辑并剥离敏感操作
对已知存在__destruct方法的类进行安全加固,消除其内部调用system()、exec()、file_put_contents()等危险函数的可能性,从根本上切断利用链。
1、检索项目中所有定义了__destruct的类,命令示例:grep -r "__destruct" ./app/ --include="*.php"
2、将file_put_contents($this->logFile, $this->logContent);替换为日志门面调用:Log::write($this->logContent, $this->logFile);,由统一日志组件管控写入路径与内容。
3、删除__destruct中所有外部系统调用,仅保留资源释放类操作(如fclose($this->handle)),并添加is_resource($this->handle)前置判断。
四、启用PHP内置反序列化防护机制
利用PHP解释器层的安全控制,在进程启动阶段限制反序列化行为,降低运行时被绕过的风险。
1、在php.ini中设置unserialize_callback_func = "my_unserialize_callback",并定义回调函数返回false以阻止未知类加载。
2、配置open_basedir限制脚本可访问的文件系统路径,防止__destruct中文件写入跳转至Web根目录或/var/www之外。
3、启用disable_functions指令,明确禁用system,exec,passthru,shell_exec,proc_open,popen,pcntl_exec等高危函数。
五、部署Web应用防火墙(WAF)规则
在网络边界层识别并拦截含典型反序列化特征的请求载荷,作为纵深防御的最后一道屏障。
1、编写正则规则匹配PHP序列化字符串特征:O:[0-9]+:"[a-zA-Z0-9_\\]+":[0-9]+:,对匹配到的GET或POST参数立即拦截。
2、检测请求体中是否存在%00*%00或%00ClassName%00等protected/private属性标识符,触发告警并丢弃。
3、监控unserialize相关错误日志(如Notice: unserialize(): Error at offset),对高频失败请求的IP实施临时封禁。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











