因为最近在回顾有关于正则方面的知识,所以突然想起来了这个知识点,整理一篇。 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写判断条件的时候使用全等号===即可。