这是在 code-breaking 中遇到的一道题目,名为:easy - pcrewaf。题目地址:http://51.158.75.42:8088
看完整道题目的代码,我们会发现用户可控的变量只有 第11行 的 $data ,而这个 $data 仅仅是用 preg_match 函数过滤了,那么必是要在 preg_match 函数上做文章。我们先来看看 preg_match 函数定义:
PHP手册告诉我们, preg_match 函数的返回值有3种,分别为(安全的写法是使用 === 运算符对返回值进行比较,手册推荐用效率更快的 strpos 函数替代 preg_match 函数):
1 | returns 1; // 如果匹配到. |
我们可以看到题目代码 第12行 直接将 preg_match 函数的返回结果作为 if语句 的条件,这样写明显存在安全隐患。.* 属于非贪婪模式,当部分正则匹配,但是不符合完整正则时,正则引擎会逐个字符减少,然后回溯匹配。举个例子:
1 | $data = '<?php phpinfo();aa' |
那么这里的递归次数是否会有限制呢?答案是肯定的,在PHP中,正则匹配的递归次数由 pcre.backtrack_limit 控制 PHP5.3.7 版本之前默认值为 10万 ,PHP5.3.7 版本之后默认值为 100万 ,该值可以通过php.ini设置,也可以通过 phpinfo 页面查看。
最后,我们通过上述技巧绕过 preg_match 函数即可。
PS:针对题目中的正则,我们可以使用 <script language="php">phpinfo();</script>
绕过(PHP < 7.x)
参考 :