PHP利用PCRE回溯次数限制绕过某些安全限制

首页

2018-12-07

由于NFA的执行过程存在回溯,所以其性能会劣于DFA,但它支持更多功能。

大多数程序语言都使用了NFA作为正则引擎,其中也包括PHP使用的PCRE库。

二、回溯的过程是怎样的所以,我们题目中的正则\.*[(`;].*,假设匹配的输入是见上图,可见第4步的时候,因为第一个.*可以匹配任何字符,所以最终匹配到了输入串的结尾,也就是//aaaaa。

但此时显然是不对的,因为正则显示.*后面还应该有一个字符[(`;]。 所以NFA就开始回溯,先吐出一个a,输入变成第5步显示的//aaaa,但仍然匹配不上正则,继续吐出a,变成//aaa,仍然匹配不上……最终直到吐出;,输入变成第12步显示的],这个结果满足正则表达式的要求,于是不再回溯。

13步开始向后匹配;,14步匹配.*,第二个.*匹配到了字符串末尾,最后结束匹配。

在调试正则表达式的时候,我们可以查看当前回溯的次数:这里回溯了8次。 三、PHP的_limit限制利用PHP为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设定了一个回溯次数上限_limit。 我们可以通过var_dump(ini_get(_limit));的方式查看当前环境下的上限:这里有个有趣的事情,就是PHP文档中,中英文版本的数值是不一样的:我们应该以英文版为参考。 可见,回溯次数上限默认是100万。

那么,假设我们的回溯次数超过了100万,会出现什么现象呢比如:可见,preg_match返回的非1和0,而是false。

preg_match函数返回false表示此次执行失败了,我们可以调用var_dump(preg_last_error()===PREG_BACKTRACK_LIMIT_ERROR);,发现失败的原因的确是回溯次数超出了限制:所以,这道题的答案就呼之欲出了。 我们通过发送超长字符串的方式,使正则执行失败,最后绕过目标对PHP语言的限制。 对应的POC如下:四、PCRE另一种错误的用法延伸一下,很多基于PHP的WAF,如:均存在上述问题,通过大量回溯可以进行绕过。

另外,我遇到更常见的一种WAF是:这里涉及到了正则表达式的「非贪婪模式」。 在NFA中,如果我输入UNION/*aaaaa*/SELECT,这个正则表达式执行流程如下:。