PHP_PCRE回溯次数限制绕过某些安全限制

2020-03-30 14:50:12 浏览数 (1)

因为最近在回顾有关于正则方面的知识,所以突然想起来了这个知识点,整理一篇。 PHP的PCRE库使用的正则引擎是NFA,不同于根据正则一步步匹配确定下一个转移状态的DFA,NFA会在正则表达式匹配不上时进行回溯,尝试其他的状态。 举一个简单的例子。

代码语言:javascript复制
preg_match('/<?.*[(`;?>].*/', $code);

当我们传入变量值如下时

代码语言:javascript复制
$code='<? phpinfo();//abcde'

通过gif图可以看到回溯了8次(刷红代表回溯) 那么这个回溯我们可以进行怎样的利用呢? 显而易见的,如果回溯次数过多,很有可能会导致DOS攻击。

PHP也早就考虑到了这一点所以给pcre设定了一个回溯上限pcre.backtrack_limit, 可以通过var_dump(ini_get('pcre.backtrack_limit'));查询,回溯上限为1000000。

那么如果我们的回溯次数超过了上限会返回什么呢?

通过这个方法我们可以绕过一些正则匹配的机制。 比如说防SQL的WAF

代码语言:javascript复制
<?php
if(preg_match('/UNION. ?SELECT/is', $input)) {
    die('sql');
}

这里如果输入

代码语言:javascript复制
$input='UNION/*aaa*/SELECT'

正则匹配的回溯次数也会随着a的数量而增加从而突破pcre.backtrack_limit的限制,进而绕过WAF。

那么如何避免自己的正则被绕过呢?搭配preg_match写判断条件的时候使用全等号===即可。

0 人点赞