MENU

File Upload

造成文件上传漏洞的原因是
对于上传文件的后缀名(扩展名)没有做较为严格的限制
对于上传文件的MIMETYPE 没有做检查
权限上没有对于上传的文件的文件权限,(尤其是对于shebang类型的文件)
对于web server对于上传文件或者指定目录的行为没有做限制

1.前端限制

function check(){
        var filename=document.getElementById("file");
        var str=filename.value.split(".");
        var ext=str[str.length-1];
        if(ext=='jpg'||ext=='png'||ext=='jpeg'||ext=='gif'){
            return true;
        }else{
            alert("这不是图片!")
            return false;
        }
        return false;
    }

用JS函数来检查 貌似没啥卵用
反制:

随便的编辑一下页面/用burpsuite/写个小脚本就可以突破之

2.检查扩展名

黑名单策略

$postfix = end(explode('.','$_POST['filename']);
if($postfix=='php'||$postfix=='asp'||$postfix=='sh'){
  echo "invalid file type";
  return;
}

白名单策略

$postfix = end(explode('.','$_POST['filename']);
if($postfix=='jpg'||$postfix=='png'||$postfix=='gif'){
  //save the file and do something next
} else {
  echo "invalid file type";
  return;
}

相对来说白名单更安全 黑名单可以突破
反制:

nginx空字节漏洞 xxx.jpg%00.php 这样的文件名会被解析为php代码运行
apache的解析漏洞,上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但是由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的

3.检查HTTP Header中的Content-Type

HTTP协议规定了上传资源的时候在Header中加上一项文件的MIMETYPE,来识别文件类型,这个动作是由浏览器完成的,服务端可以检查此类型不过这仍然是不安全的,因为HTTP header可以被发出者或者中间人任意的修改
反制:

改请求头中的Content-Type

4.分析文件头内容来检查文件类型

利用每一个特定类型的文件都会有不太一样的开头或者标志位,可以通过比如php的exif_imagetype()函数,示例

 if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) {
        echo "File is not an image";
        return;
    }

通过检查头几位字节,可以分辨是否是图片文件
JPG

FF D8 FF E0 00 10 4A 46 49 46

GIF

47 49 46 38 39 61

PNG

89 50 4E 47

反制:
给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解释而跳过之,后面的代码仍然能够得到执行

GIF89a
<?php
do_something();
?>

其他类型文件对应的文件头

格式文件头
TIFF (tif)49492A00
Windows Bitmap (bmp)424D
CAD (dwg)41433130
Adobe Photoshop (psd)38425053
Rich Text Format (rtf)7B5C727466
MS Word/Excel (xls.or.doc)D0CF11E0
MS Access (mdb)5374616E64617264204A
ZIP Archive (zip)504B0304
RAR Archive (rar)52617221
Wave (wav)57415645
AVI (avi)41564920
Real Media (rm)2E524D46
MPEG (mpg)000001BA
MPEG (mpg)000001B3
Quicktime (mov)6D6F6F76
Adobe Acrobat (pdf)255044462D312E
Windows Media (asf)3026B2758E66CF11

5.限制Web Server对于特定类型文件的行为

导致文件上传漏洞的根本原因在于服务把用户上传的本应是数据的内容当作了代码,一般来说,用户上传的内容都会被存储到特定的一个文件夹下,比如我们很多人习惯于放在 ./upload/ 下面要防止数据被当作代码执行,我们可以限制web server对于特定文件夹的行为。
大多数服务端软件都可以支持用户对于特定类型文件的行为的自定义,以Apache为例:

在默认情况下,对与 .php文件Apache会当作代码来执行,对于 html,css,js文件,则会直接由HTTP Response交给客户端程序对于一些资源文件,比如txt,doc,rar等等,则也会以文件下载的方式传送的客户端。我们希望用户上传的东西仅仅当作资源和数据而不能当作代码
因此可以使用服务器程序的接口来进行限制

以Apache为例,我们可以利用 .htaccess 文件机制来对web server行为进行限制
在这里插一句,如果不是专门的文件下载目录,请务必关掉文件夹浏览的权限,以防止嗅探和可能的越权,也是使用.htaccess文件,在其中加上一句

Options All -Indexes

即可。

禁止脚本执行有多种方式可以实现,而且分别有不同的效果,我们分别来看一下
1.指定特定扩展名的文件的处理方式,原理是指定Response的Content-Type可以加上如下几行

AddType text/plain .pl .py .php

这种情况下,以上几种脚本文件会被当作纯文本来显示出来,你也可以换成其他的Content-Type

2.如果要完全禁止特定扩展名的文件被访问,用下面的几行

Options -ExecCGI
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi

在这种情况下,以上几种类型的文件被访问的时候,会返回403 Forbidden的错误
3.也可以强制web服务器对于特定文件类型的处理,与第一条不同的是, 下面的方法直接强行让apache将文件识别为你指定的类型,而第一种是让浏览器

<FilesMatch "\.(php|pl|py|jsp|asp|htm|shtml|sh|cgi)$">
ForceType text/plain
</FilesMatch>

看代码就可以很明白的知道,符合上面正则的全部被认为是纯文本,也可以继续往里面加入其他类型。
4.只允许访问特定类型的文件

<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>

在一个上传图片的文件夹下面,就可以加上这段代码,使得该文件夹里面只有图片扩展名的文件才可以被访问,其他类型都是拒绝访问。
这又是一个白名单的处理方案
永远记得,白名单是最有保障的安全措施
反制:
可以通过 move_uploaded_file 函数把自己写的.htaccess 文件上传,覆盖掉服务器上的文件,来定义文件类型和执行权限如果做到了这一点,将获得相当大的权限。

最后 这些都不是我写的

Tags: CTF, WEB
Archives QR Code
QR Code for this page
Tipping QR Code