PHP利用pcre回溯次数限制的绕过waf
参考p神博客:PHP利用PCRE回溯次数限制绕过某些安全限制 | 离别歌 (leavesongs.com)
参考p神的代码进行分析
1 |
|
对输入内容进行判断,查看是否有被过滤的内容,如果没有则写入文件。
过滤内容大致是不允许写php代码
对此题如何绕过is_php()来写入进项php代码研究
对正则表达式的深入理解
常见的正则引擎分为DFA(确定性有限状态自动机)与NFA(非确定性有限状态自动机)
DFA: 从起始状态开始,一个字符一个字符地读取输入串,并根据正则来一步步确定至下一个转移状态,直到匹配不上或走完整个输入
NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态
NFA执行存在回溯,性能会比DFA差,但是NFA支持的功能更多。
PHP的PCRE库中就使用了NFA作为正则引擎,所以会存在回溯
回溯过程:
利用在线工具对正则回溯进行分析:嗨正则-正则表达式在线测试与调试工具
正则表达式为:
1 |
|
测试文本为:
1 |
|
点击正则执行步骤
我们可以看到最终匹配结果为
1 |
|
可以查看每一步匹配的字符
step1:
step2:
step3:
step4:
step5:
step6:
step7:
step8:
step9:
step10:
step11:
step12:
step13:
step14:
我们可以发现在step3的时候.*匹配了后面全部字符串,这显然不对
因为后面的 [(`;?>] 还没有匹配
所以在step5处开始回溯
依次吐出一个字符
直到 [(`;?>] 匹配到 ; 回溯结束
.*匹配剩下的字符串,匹配成功
显示红色的表示回溯,一共回溯了8次
对PHP的pcre.backtrack_limit限制利用
因为回溯会降低服务的性能,大量的回溯则会产生reDOS
所以php为了防止正则表达式的拒绝服务攻击(reDOS)
给pcre设定了回溯次数上限 pcre.backtrack_limit
可以通过 var_dump(ini_get(‘pcre.backtrack_limit’));
来查看当前环境对回溯次数的限制
参考英文版的PHP文档
默认回溯次数为100万,如果回溯次数超过100万那么preg_match会返回false
意思就是匹配失败,意味着我们就可以通过发超长字符串,使得正则匹配失败绕过PHP语言限制
POC
1 |
|
CTF实战:[FBCTF 2019]rceservice | NSSCTF
1 |
|
可以看到过滤了很多东西
要求JSON命令来输入,就是键值对的方法
putenv('PATH=/home/rceservice/jail');
将环境变量PATH
设置为/home/rceservice/jail
这意味着任何命令的执行都将仅限于此路径下的可执行文件。
在这种情况下,除非/home/rceservice/jail
目录中存在cat
命令,否则默认路径下的cat
命令将不可用。
通常情况下,cat
命令在系统的/bin
目录中,这意味着你需要指定完整路径/bin/cat
才能执行cat
命令。
推测flag在/home/rceservice/目录下
可以用脚本验证
直接拿脚本跑
1 |
|
其他解法:
当看到正则中存在^xxx$格式也会用%0a:%0a绕过
1 |
|