PCRE绕过正则
4 分钟
前言
今天进行CTF刷题的时候,刷到了关于正则表达式贪婪匹配后进行回溯产生的绕过,记录一下。
一、PCRE绕过的原理
正则表达式是一个可以被“有限状态自动机”接受的语言类。
有限状态自动机",其拥有有限数量的状态,每个状态可以迁移到零个或多个状态,输入字串决定执行哪个状态的迁移。
而常见的正则引擎,又被细分为DFA(确定性有限状态自动机)与NFA(非确定性有限状态自动机)。他们匹配输入的过程分别是:
- DFA: 从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入
- NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态
由于NFA的执行过程存在回溯,所以其性能会劣于DFA,但它支持更多功能。大多数程序语言都使用了NFA作为正则引擎,其中也包括PHP使用的PCRE库。
比如说:
假如传入$data=
问题在于: PHP为了防止对正则表达式进行拒绝服务攻击,设置了pcre.backtrack_limit的配置,限制正则表达式的回溯次数:
查看回溯次数,默认上限为100万次,当回溯次数超过100万次,就会使preg_match函数返回false,说明此次正则匹配执行失败。
防御方法:要防御正则表达式的回溯次数溢出,将preg_match的结果使用强等于===匹配即可。
二、例题
1.[NISACTF 2022]middlerce
题目源码:
|\{|\x09|\x0a|\[).*$/m',$txw4ever)){
die("再加把油喔");
}
else{
$command = json_decode($txw4ever,true)['cmd'];
checkdata($command);
@eval($command);
}
}
else{
highlight_file(__FILE__);
}
?>
1,题目从头开始进行正则表达式匹配,.贪婪匹配后又匹配括号里的字符,最后再.后结束
checkdata函数进行的是黑名单过滤,可以使用tail以及通配符*进行获取flag,过滤了
/\^|\||\~|assert|print|include|require|\(|echo|flag|data|php|glob|sys|phpinfo|POST|GET|REQUEST|exec|pcntl|popen|proc|socket|link|passthru|file|posix|ftp|\_|disk|tcp|cat|tac/i
2,代码虽然执行了eval函数,但是却不会将结果输出到页面,可以使用短标
3,关键点在于使回溯次数超过100万次,返回false,利用脚本上传post数据:
data = '{"cmd":"?>", "#":"' + "#" * 1000000 + '"}'
其中.*会匹配掉整个字符串,但是此时不正确,因为后面括号应该还有字符,会进行回溯,传入一百万个#会使回溯次数上限,返回false绕过正则匹配。
~ ~ The End ~ ~
分类标签:CTF,CTF
文章标题:PCRE绕过正则
文章链接:https://aiwin.fun/index.php/archives/995/
最后编辑:2024 年 1 月 5 日 21:10 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
文章标题:PCRE绕过正则
文章链接:https://aiwin.fun/index.php/archives/995/
最后编辑:2024 年 1 月 5 日 21:10 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)