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  ~  ~


 赏 
承蒙厚爱,倍感珍贵,我会继续努力哒!
logo图像
tips
文章二维码 分类标签:CTFCTF
文章标题:PCRE绕过正则
文章链接:https://aiwin.fun/index.php/archives/995/
最后编辑:2024 年 1 月 5 日 21:10 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
(*) 7 + 7 =
快来做第一个评论的人吧~