PHP利用PCRE回溯次数限制绕过waf

学习文章:https://www.leavesongs.com/PENETRATION/use-pcre-backtrack-limit-to-bypass-restrict.html

前置知识:正则表达式

常见的正则分为DFA(确定性有限状态自动机)和NFA(非确定性有限状态自动关机)

  • DFA:从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入
  • NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态

NFA执行过程存在回溯,性能劣于DFA,但它支持更多功能,大多数程序语言都是用了NFA作为正则引擎,其中也包括PHP使用的PCRE库

回溯过程解析

示例代码

1
2
3
4
5
6
7
8
<?php
function is_php($data){
return preg_match('/<\?.*[(`;?>].*/is', $data);
}

if(!is_php($input)) {
// fwrite($f, $input); ...
}

这题中的正则是<?.*[(`;?>].*

  • <?:匹配<?
  • .*:匹配任意长度的任意字符
  • [(`;?>]:字符类,表示匹配其中的任何一个字符
  • 修饰符i:不区分大小写
  • 修饰符s:让.匹配换行符

假设输入的是<?php phpinfo();//aaaaa,那么实际执行的流程是这样的

image-20260603200459935

见第4步,第一关.*可以匹配任意字符,所以最终能够匹配到输入串的结尾,就是//aaaaa,但这里是不对的,因为第一关.*后面还应该有[(`;?>]字符去匹配

所以这里NFA就开始回溯,先匹配到输入串结尾的前一位,即少匹配一个a,如第5步显示,但仍然匹配不上正则,所以还要继续少匹配一个a,依次类推,直到只匹配到<?php


PHP利用PCRE回溯次数限制绕过waf
https://colourful228.github.io/2026/06/03/PHP利用PCRE回溯次数限制绕过waf/
作者
Colourful
发布于
2026年6月3日
更新于
2026年6月3日
许可协议