相关文章推荐
腼腆的小摩托  ·  MySQL 客户端报错 no ...·  3 月前    · 
从容的蚂蚁  ·  VBA ...·  1 年前    · 
var flag = false ; var str = document.getElementById( " file " ).value; str = str.substring(str.lastIndexOf( ' . ' ) + 1 ); var arr = new Array( ' png ' , ' bmp ' , ' gif ' , ' jpg ' ); for ( var i= 0 ;i<arr.length;i++ ) if (str== arr[i]) flag = true ; if (! flag) alert( ' 文件不合法! ' ); return flag; </script> </head> <form action= " upload.php " method= " post " onsubmit= " checkFile() " enctype= " multipart/form-data " > <input type= " file " name= " file " id= " file " /><br/> <input type= " submit " value= " 提交 " name= " submit " /> </form> </body> </html>

接收文件的脚本upload.php代码如下:

<?php
    if(isset($_POST["submit"]))
        $name = $_FILES['file']['name'];
        $name = md5(date('Y-m-d h:m:s')).strrchr($name,".");
        $size = $_FILES['file']['size'];
        $tmp = $_FILES['file']['tem_name'];
        move_uploaded_file($tmp,$name);
        echo "文件上传成功!path:".$name;
1、可以用firebug将form表单中的onsubmit事件删除,这样就可以绕过验证。
2、使用Burp Suite:
      1)先将木马文件的扩展名改为一张正常图片的扩展名,如1.php/asp --->  1.jpg
      2)上传时使用Burp Suite拦截数据包,将木马文件扩展名改为php就可绕过客户端验证。
注意:这里修改文件名字后,请求头中的Content-Length的值也要改

服务端检测

服务端分为6项:
  • 黑名单与白名单验证
  • MIME验证
  • 截断上传攻击
  • .htaccess文件攻击
  • 检测文件内容
  • 黑名单与白名单验证

    黑名单过滤方式

    <?php
    $Blacklist = array('asp','php','jsp','php5','asa','aspx'); //黑名单
    if(isset($_POST["submit"]))
            $name = $FILES['file']['name'];                  //接收文件名
            $extension = substr(strrchr($name, ".") , 1);    //得到扩展名
            $boo = false;
            foreach($Blaklist as $key => $value)
                if($value==$extension) 
                    //迭代判断是否命中
                    $boo = true;
                    break; //命中后直接退出循环
           if(!$boo) 
              //若没有被命中,则进行上传操作
              $size = $_FILES['file']['size'];       //接收文件大小
              $tmp = $FILES['file']['temp_name'];    //临时路径
              move_uploaded_file($tmp, $name);       //移动临时文件到当前文件目录
              echo "文件不合法!!";
    
    对于上面的过滤可以通过如下方法绕过:
  • 从黑名单中找到web开发者忽略的扩展名,如:cer
  • 没有对扩展名进行大小写转换,在window平台依然可以大小写绕过
  • 在window下,若文件名以"."或者空格作为结尾,系统会自动去除"."与空格,
    所以可以上传以“asp.”和“asp_”为扩展名的文件
  • 0x00截断绕过
  • <?php
    $WhiteList = array('rar','jpg','png','bmp','gif','jpg','doc');
    if(isset($_POST["submit"]))
           $name = $_FILES['file']['name'];
           $extension = substr(strrchr($name,"."),1);
           $boo = false;
           foreach($WhiteList as $key => $value)
               if($value==$extension)
                   $boo = true;
           if($boo)
                 $size = $_FILES['file']['size'];
                 $tmp = $_FILES['file']['tmp_name'];
                 move_uploaded_file($tmp,$name);
                 echo "文件上传成功!<br/>path:".$name;
                 echo "文件不合法!";
    
    绕过方法:
  • 0x00截断绕过
  • 此时若在iis6.0,则可以将木马名改为test.asp;1.jpg来上传,从而通过验证
  • 配合解析漏洞
  • MIME验证

    对文件MIME类型做验证的PHP代码如下:

    <?php
         if($_FILES['file']['type']==" image/jpeg")
                $imageTempName = $_FILES['file']['tmp_name'];
                $imageName = $_FILES['file']['name'];
                $last = substr($imageName,strrpos($imageName,"."));
                if(!is_dir("uploadFile"))
                    mkdir("uploadFile");
                $imageName = md5($imageName).$last;
                move_upload_file($imageTempName,"./uploadFile/".$imageName);
                echo("文件上传成功! path = /uploadFile/$imageName");
                echo("文件上传类型错误,请重新上传...");
                exit();
    
    未修改MIME类型,上传失败:

    修改MIME类型,上传成功:

    <form action="upload.php" method="post" enctype="multipart/form-data"> <input type="file" name="file" /><br/> <input type="hidden" name="Extension" value="up" /> <input type="submit" value="提交" name="submit" /> </form> </body> </html>
    服务端PHP接收文件的代码如下:
    <?php
         if($_FILES['file']['type']=="image/jpeg")
               $imageTempName=$_FILES['file']['tmp_name'];
               $imageName=$_FILES['file']['name'];
               $last=substr($imageName,strrpos($imageName,"."));
               if($last!=".jpg")
                  echo("mime error!<br/>");
              $Extension=$_POST['Extension'];
              if(!is_dir($Extension))
                  mkdir("./$Extension");
                  echo "mkidr $Extension succesfully"."<br/>";
              $imageName=md5($imageName).$last;
              move_uploaded_file($imageTempName,"./$Extension/".$imageName);
              echo("upload ok! path = /$Extension/$imageName");
            echo("type error...");
            exit();
    
    查看上传到了那个文件:

    将文件改名:

    .htaccess文件攻击

    通过.htaccess文件调用php解析器去解析一个文件名中只要包含"haha"这个字符串的任意文件,论扩展名是什么(没有也行),都以php的方式来解析,.haccess文件代码如下

    <FilesMatch "haha">
    SetHandler application/x-httpd-php
    </FilesMatch>
    或者如下,上传一个文件名为evil.gif的图片马:
    <FilesMatch "evil.gif">
    SetHandler application/x-httpd-php
    </FilesMatch>
    除了上述的.htaccess文件攻击,还可以用.user.ini进行文件攻击
    当中间键是以fastcgi运行的php都可以用这个方法,.user.ini能被动态加载,它也有两个配置项:
    auto_append_file和auto_prepend_file,只要在.user.ini中添加auto_prepend_file=aa.jpg
    这句话,就可以让其他php文件执行前自动包含aa.jpg,和require()类似。

    1 使用大小写绕过(针对对大小写不敏感的系统如windows),如:PhP

    2 使用黑名单外的脚本类型,如:php5

    3 借助文件解析漏洞突破扩展名验证,如:test.jpg.xxx(apache解析漏洞)

    4 借助系统特性突破扩展名验证,如:test.php_(在windows下下划线是空格,保存文件时下划线被吃掉剩下test.php)

    5 双扩展名之间使用00截断,绕过验证上传恶意代码如:test.php%00.jpg

    6 借助.htaccess文件上传恶意代码并解析。如:上传一个.htaccess文件,内容为AddTypeapplication/x-httpd-php .jpg,上传的jpg文件就可以当作php来解析

    7 使用00截断,绕过后缀验证获取webshell(php<5.3.4+关闭GPC)

    8 超长文件名截断上传(windows 258byte | linux 4096byte)

    1 使用白名单限制可以上传的文件扩展

    2 验证文件内容,使用正则匹配恶意代码限制上传

    3 对上传后的文件统一随机命名,不允许用户控制扩展名

    4 修复服务器可能存在的解析漏洞

    5 严格限制可以修改服务器配置的文件上传如:.htaccess