php 正则 回溯,preg_match正则最大回溯以及preg_match函数的绕过

先提出一段代码,是i春秋上面的移到ctf题目的代码,也是需要我们绕过的代码:

function areyouok($greeting){

return preg_match('/Merry.*Christmas/is',$greeting);

}

$greeting=@$_POST['greeting'];

if(!areyouok($greeting)){

if(strpos($greeting,'Merry Christmas')!==false){

echo 'Merry Christmas. '.'flag{xxxxxx}';

}else{

echo 'Do you know .swp file?';

}

}else{

echo 'Do you know PHP?';

}

?>

很快就可以知道,使用数组就可以绕过

payload:

greeting[]=Merry Christmas&greeting[]=123

21d6cad3642b621fc0f2d3894d80cf21.png

但是如果禁止传递数组的时候怎么绕过?

示例代码(来自i春秋ctf):

function areyouok($greeting){

return preg_match('/Merry.*Christmas/is',$greeting);

}

$greeting=@$_POST['greeting'];

if(!is_array($greeting)){

if(!areyouok($greeting)){

if(strpos($greeting,'Merry Christmas')!==false){

echo 'Merry Christmas. '.'flag{xxxxxx}';

}else{

echo 'Do you know .swp file?';

}

}else{

echo 'Do you know PHP?';

}

}

?>

其中判断了greeting不能为数组,这时就涉及到一个关于正则最大回溯的问题了

正则(pcre)最大回溯:

在PHP的pcre扩展中提供了两个设置选项:

pcre.backtrack_limit //最大回溯数

pcre.recursion_limit //最大嵌套数

d328b01b9b673657ae0efd8ca597d348.png

backtrack_limit的默认值为100000。

而什么是回溯?

在正则匹配当中,如果存在符号 " .*? " ,那么匹配的时候便会使用非贪婪模式。非贪婪模式匹配原理简单来说就是, 在可配也可不配的情况下, 优先不匹配. 记录备选状态, 并将匹配控制交给正则表达式的下一个匹配字符, 当之后的匹配失败的时候, 再回溯, 进行匹配。

举例来说:

源字符串: aaab

正则: .*?b

匹配过程开始的时候, “.*?”首先取得匹配控制权, 因为是非贪婪模式, 所以优先不匹配, 将匹配控制交给下一个匹配字符”b”, “b”在源字符串位置1匹配失败(“a”), 于是回溯, 将匹配控制交回给”.*?”, 这个时候, “.*?”匹配一个字符”a”, 并再次将控制权交给”b”, 如此反复, 最终得到匹配结果, 这个过程中一共发生了3次回溯。

所以在题目当中,只要匹配时的回溯次数超过了100000,就会导致匹配失败而退出,从而绕过限制。

所以我们的payload应该为:

greeting=Merry Christmas //后面省略数万个字符

这样即可绕过限制。

参考链接:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值