一次对PHP正则绕过的思考历程
字数 1271 2025-08-09 09:46:33
PHP正则表达式绕过技术深度解析
0x00 前言
本文详细分析PHP中基于正则表达式的安全过滤机制存在的多种绕过方法,涵盖XSS防护和PHP标签过滤的绕过技术。这些技术在实战渗透测试和CTF比赛中具有重要应用价值。
0x01 目标函数分析
过滤函数代码
function checkstr($str) {
// 第一层过滤:拦截特定HTML标签和PHP标签
if (preg_match("/<(\/?)(script|i?frame|style|html|\?php|body|title|link|meta)([^>]*?)>/is", $str, $match)) {
return false;
}
// 第二层过滤:拦截HTML标签中的on事件属性
if (preg_match("/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/is", $str, $match)) {
return false;
}
return true;
}
第一层过滤分析
正则表达式:/<(\/?)(script|i?frame|style|html|\?php|body|title|link|meta)([^>]*?)>/is
-
修饰符:
i:不区分大小写s:使.匹配包括换行符在内的所有字符
-
分组解析:
(\/?):匹配可选的/字符(用于闭合标签)(script|i?frame|style|html|\?php|body|title|link|meta):匹配黑名单标签([^>]*?):非贪婪匹配任意非>字符,直到遇到>
拦截目标:
<script>、</script><iframe>、<frame><?php ... ?>等PHP标签- 其他黑名单中的HTML标签
第二层过滤分析
正则表达式:/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/is
- 分组解析:
(<[^>]*):贪婪匹配<后所有非>字符on[a-zA-Z]+\s*=:匹配on开头的事件属性([^>]*>):匹配剩余部分直到>
拦截目标:
- ``
<tag onxxxx="malicious code">- 其他包含
on事件的HTML标签
0x02 绕过技术详解
2.1 绕过PHP标签过滤
场景:文件写入漏洞,需要写入PHP代码
方法1:使用替代PHP标签
<?= phpinfo(); ?> <!-- 短标签语法 -->
<? phpinfo(); ?> <!-- 需要开启short_open_tag -->
方法2:省略闭合标签
<?php phpinfo(); // 不闭合,避免匹配到?>
方法3:使用__halt_compiler()
<?php phpinfo();__halt_compiler();
方法4:伪协议编码绕过
php://filter/write=convert.base64-decode/resource=shell.php&c=PD9waHAgcGhwaW5mbygpOz8+
2.2 绕过XSS过滤
方法1:使用非事件属性执行JS
<object data=javascript:alert(1)>
方法2:利用标签属性优先级
"/onerror=alert(1);>
原理:双引号的优先级高于>,使正则匹配失败但浏览器仍能解析
2.3 正则回溯绕过
条件:
preg_match返回值未使用全等(===)判断- 输入字符串能导致大量回溯
方法1:针对非贪婪匹配的回溯
<?php //[大量a字符]?>
方法2:针对贪婪匹配的回溯
原理:当回溯次数超过pcre.backtrack_limit(默认100万)时,preg_match返回false
0x03 防御建议
-
替代方案:
- 使用
htmlspecialchars()进行HTML实体编码 - 对文件名进行重命名(如MD5+时间戳)
- 使用
-
正则改进:
- 避免使用非贪婪匹配
*?在关键位置 - 对
preg_match返回值使用全等判断===
- 避免使用非贪婪匹配
-
配置调整:
- 禁用不必要的PHP标签类型
- 限制输入长度防止回溯攻击
0x04 总结
本文详细分析了PHP正则过滤机制的多种绕过技术,包括:
- PHP标签的替代写法
- HTML标签解析差异利用
- 正则引擎回溯特性攻击
- 编码转换绕过
这些技术展示了黑名单过滤的固有弱点,强调了使用白名单和编码转换等更安全方法的重要性。