文件上传

文件上传

web漏洞文件上传.png

概念

文件上传漏洞是指用户上传了一个可执行的脚本文件webshell,而且通过这个脚本文件获得了执行服务器端命令的能力。

Webshell 以 ASP、PHP、JSP 等网页文件形式存在的一种命令执行环境,也称其为一种网页后门,通过 Webshell 可以对所在服务器进行远程管理。

危害

非法用户可以利用上传的恶意脚本文件WebShell控制整个网站,甚至控制服务器。也可将WebShel脚本称为一 种网页后门,WebShel脚本具有非常强大的功能,比如查看服务器目录、服务器中的文件,执行系统命令等。

  • 网站被植入黑链(博彩、黄色)
  • 挖矿
  • 文件泄露

产生原因

前端或者服务端代码未对客户端上传的文件进行严格的验证和过滤。

文件上传漏洞发生的前提

1、网站上传功能能正常使用
2、文件类型允许上传
3、上传路径可以确定
4、文件可以被访问,可以被执行或被包含

查找和判断

黑盒查找:不知道源代码情况下,通过目录扫描和网站应用,以及通过网站后台、会员中心进行获取权限,需要自己判断。

白盒查找:通过源代码分析文件上传漏洞。

判断:通过抓包分析

文件上传的分类

文件上传利用思路.png

  • 常规类

  • CMS类

    CMS 又叫网站内容管理系统(网站的模版,帮助我们快速建站,我们会在这个网站模板上做二次开发),市面上很多开源的CMS 的历史版本有很多都存在着文件上传漏洞,但是产生文件上传漏洞的原因不尽相同。

    比如常见的dedeCMS(织梦)、PHPcms、Seacms 等。

    参考:https://blog.csdn.net/qq_35733751/article/details/115317967

  • 编辑器类

    编辑器就是网站后台编辑网页的在线编辑器,会自动集成文件上传功能,这些编辑器的某些版本也存在文件上传漏洞,从而进行getshell

    比如ewebeditor、fckeditor。

    参考:https://www.likecs.com/show-203442332.html

  • CVE

    比如,Weblogic任意文件上传漏洞( CVE-2018-2894 )

文件上传的利用

  • 找到上传的位置

    常规文件上传地址的获取说明:

    比如搜索引擎搜索inurl:upload.php、网站的目录扫描(御剑)、针对网站搜索upload关键词site:abc.com upload、网站自身的应用(上传头像、图片等)。

  • 尝试绕过校验,上传php文件

    upload-fuzz-dic-builder 上传漏洞fuzz字典生成脚本:https://github.com/c0ny1/upload-fuzz-dic-builder

    文件上传攻击一般配合文件解析漏洞,比如nginx解析漏洞。具体可以看文件上传攻击的防护及绕过。

  • 获得文件位置

    上传文件后,要想执行,必须先获取文件路径。可以拖动上传的文件到新标签页得到文件路径,或者看看URL、或者看网站有没有查看所上传文件的地方。

  • 蚁剑/菜刀连接,管理文件

文件上传攻击的防护及绕过

img

**使用github上的靶场:upload labs**(场景比DVMA更丰富),下载下来放在本地网站localhost里(phpstudy或者apache+php)。

fuzz字典:https://github.com/c0ny1/upload-fuzz-dic-builder,包含可能的攻击语句。结合BP使用。

image-20220728153545912

防护思路

  1. 后端验证:采用服务端验证模式(不采用前端验证)

  2. 下面三种检测方式同时进行:

    • 后缀检测:基于黑名单,白名单过滤

    • MIME 检测:基于上传自带类型检测

    • 内容检测:文件头,完整性检测

  3. 自带函数过滤(就PHP脚本而言)

    比如getimagesize()函数检查文件头;exif_imagetype()函数检查文件类型等等

  4. 自定义函数过滤:function check_file(){}

    结合黑名单和白名单,可以两者相互嵌套

  5. WAF 防护产品:宝塔,云盾,安全公司产品等

    如果存在waf,就无法判断是否存在文件上传漏洞,只有一一尝试。

1. 前端限制文件类型(白名单)

破解方法一:直接F12,删除(禁用)前端的限制文件类型的JS脚本。上传成功后,拖动图片到新标签页得到文件路径。

破解方法二:先上传网站允许的文件后缀,然后BP抓包修改文件后缀为php。

2. MIME类型

参考upload-labs Pass-2。

在访问网页时,MIME type帮助浏览器识别一个HTTP请求返回的是什么内容的数据,应该如何打开、如何显示。作用和文件拓展名相似,但不同的是它并非标注文件,而是在邮件和HTTP协议中用来标注网络数据的。

客户端使用:

1、GET请求不需要这个字段。
2、POST请求头,放在Content Type字段 用来指定上传的文件类型,方便服务器解析。放在Accept, 告诉服务端允许接收的响应类型。比如只能接收json或者其他。

服务端使用:

1、放在响应头里面,Content Type 告诉客户端响应的数据类型,方便客户端解析。

MIME 描述
text/html HTML格式
application/json JSON数据格式
multipart/form-data 文件上传(二进制数据)
image/jpeg、image/gif、image/pjpeg jpg、gif、pjpeg图片格式

MIME类型的确定根据的是文件扩展名。

破解方法:BP抓包,修改MIME类型为image/jpeg即可绕过上传。

3. 文件后缀黑名单

参考upload-labs Pass-4。

禁止asp、php等类型文件上传。

破解方法:使用等价扩展名。

语言 等价扩展名
asp asa,cer,cdx
aspx ashx,asmx,ascx
php php2、 php3、 php4、 php5、 phps、 phtml
jsp jspx.jspf

文件后缀绕过

文件后缀绕过攻击是服务端代码中限制了某些后缀的文件不允许上传,但是有些Apache是允许解析其他文件后缀的,例如在httpd.conf中,如果增加其他后缀shell.php.phtml,则能够解析php和phtml文件。

在Apache的解析顺序中,是从右到左开始解析文件后缀的,如果最右侧的扩展名不可识别,就继续往左判断,直到遇到可以解析的文件后缀为止,所以如果上传的文件名类似1.php.xxxx,因为后缀xxxx不可以解析,所以向左解析后缀php。而服务器如果使用php的pathinfo()来获取文件后缀,那么只会看到后缀xxxx,因此实现了绕过。

4. 很全的黑名单+大小写模糊(.htaccess绕过)

黑名单更多了一些,不过没有过滤.htaccess后缀,参考upload-labs Pass-4。

先按照如下代码块的内容写一个新的.htaccess文件,然后上传,使其处于所有上传文件所在的目录。

htaccess: Hypertext Access(超文本入口)
它是一个纯文本文件,它里面存放着Apache服务器配置相关的指令。
作用:伪静态、图片防盗链、自定义404错误页面、阻止/允许特定IP/IP段、目录浏览与主页、禁止访问指定文件类型、文件密码保护

1
2
3
4
5
6
<FilesMatch "test.png">  
SetHandler application/x-httpd-php
</FilesMatch>

或者
AddType application/x-httpd-php png

然后将php文件修改为.htaccess文件所指定的图片文件后缀或文件名,然后上传。因为.htaccess文件被修改,所以直接访问该图片文件时其会被服务器当作PHP文件解析。

.htaccess生效的前提:

httpd.conf设置AllowOverride all,而不是none,所以phpstudy集成的apache会无法实验成功。

5. 黑名单过滤,没有考虑大小写

过滤htaccess后缀,但是没有过滤php全部的大小写,使用后缀pHp即可绕过上传。参考upload-labs Pass-5。

shell.pHp

6. 黑名单过滤,没有对后缀去空

在判断后缀名的时候没有先去除多余的空格。参考upload-labs Pass-6。

后缀名后添加空格即可绕过后端php脚本的检测,再上传到windows服务器上,会自动去除后缀名后的空格。

shell.php (php后面有空格)

7. 黑名单过滤,没有过滤点

添加点即可绕过后端的php检测,而且可以正常解析。参考upload-labs Pass-7。

shell.php.

另外,遇到move_uploaded_file()函数时,其有这么一个特性,会忽略掉文件末尾的 /.
所以直接上传php文件,然后抓包,添加/. 就可以绕过黑名单。参考upload-labs Pass-19。

shell.php/.

【upload-labs Pass-20】

查看该题源码可知,若提交的保存的文件名save_name不是数组,那就以点来分割得到数组$file。而下面的EXP则是直接提交数组。

该页面会将数组的最后一个元素看作后缀名进行白名单校验,通过校验后将第一个元素和点以及最后一个元素拼接得到文件名。但是在取最后一个元素时存在漏洞:$file_name = reset($file) . '.' . $file[count($file) - 1];。可以看如下POST请求体,save_name[0]为shell.php/,save_name[2]为jpg,这样校验后缀名时取的是index为2的jpg。但是在拼接文件名时,由于未给save_name[1]赋值,所以count($file)的结果是2而非3,所以$file[count($file) - 1]的值为空,而非jpg。最后得到的文件名就为shell.php/.,又由于move_uploaded_file()函数会忽略这个/.,所以该文件会被保存为shell.php。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
------WebKitFormBoundary0lAKZaGSiktCjkBi
Content-Disposition: form-data; name="upload_file"; filename="shell.php"
Content-Type: image/png

<?php
phpinfo();
?>
------WebKitFormBoundary0lAKZaGSiktCjkBi
Content-Disposition: form-data; name="save_name[0]"

shell.php/
------WebKitFormBoundary0lAKZaGSiktCjkBi
Content-Disposition: form-data; name="save_name[2]"

jpg
------WebKitFormBoundary0lAKZaGSiktCjkBi
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundary0lAKZaGSiktCjkBi--

8. 黑名单过滤,没有过滤::$DATA

参考upload-labs Pass-8。

在 Windows 操作系统中,::$DATA 是一种用于隐藏文件的特殊附加数据流(Alternate Data Stream)。它是一种扩展文件属性,可以将额外的数据附加到一个文件中,而不会影响文件的主要内容。
附加数据流基于文件名和冒号之间的特殊语法,例如:file.txt::D A T A 。附加数据流可以储存任意类型的数据,例如文本、二进制文件或其他文件。这使得 : : DATA。附加数据流可以储存任意类型的数据,例如文本、二进制文件或其他文件。 这使得 ::DATA。附加数据流可以储存任意类型的数据,例如文本、二进制文件或其他文件。这使得::DATA 可以被用于隐藏文件内容、存储元数据或其他需要与主文件相关但不希望直接显示给用户的信息。

shell.php::$DATA

9. 黑名单过滤,改变符号或者多次换行

比如BP抓包后,将双引号变为单引号,或者去掉文件名的双引号:

1
2
Content-Disposition: form-data;name="uploadfile"; filename=info4.php
Content-Type: image/jpeg

或者只用一个双引号(引号没有闭合,安全狗会误以为是程序自带):

1
2
Content-Disposition: form-data;name="uploadfile"; filename="info5.php
Content-Type: image/jpeg

或者文件名内多次换行:

1
2
3
4
5
Content-Disposition: form-data; name="upload_file"; filename="x.
p
h
p"
Content-Type: image/jpeg

10. 黑名单,绕过

.jpg;.php

分号;代表语句的结束,安全狗检测文件名字符串时,检测到jpg就结束了,后面的.php略过。

11. 删除黑名单字段(==重复数据==绕过)

黑名单包括php、asp

破解:文件名双写:比如shell.pphphp

12. 白名单(get的%00==截断绕过==)

参考upload-labs Pass-11。

严格限制后缀为某几种,但是请求路径使用的是get请求(request请求)。

get请求会根据文件路径做了一个00截断,../upload/1.php%00check.jpg不会被白名单过滤,而且请求后路径就被截断,变成../upload/1.php

00截断的操作环境需魔术引用开关magic_quotes_gpc为off状态,不然%00会被转义,导致攻击失效。

魔术引用开关magic_quotes_gpc会转义以下字符:

单引号(’)
双引号(”)
反斜杠(\)
NULL

但是,该方法只能绕过接收参数时的判断,如果服务器对请求后得到的路径再进行白名单的判断,因为已经被get请求截断了,后缀变成php,还是会被检测到。

13. 白名单(post的%00截断绕过)

参考upload-labs Pass-12。

严格限制后缀为某几种,但是请求路径使用的是post请求(request请求)。

post需要通过BP抓包修改数据包的文件名后缀部分,需要用二进制的方式去修改。

img

14. ==判断文件头==(图片马)

参考upload-labs Pass-14-17。

使用了 getimagesize( $uploaded_tmp ) 来获取文件头中的图片尺寸信息,读取不到尺寸信息则拒绝上传。

此时可以使用图片马,文件后缀依然为php。此时webshell可以被解析为脚本,同时getimagesize也可以获取到图片信息。

1
cat huaji.jpg shell.php > shell.php

15. 判断文件头且限制后缀

使用 strrpos( $uploaded_name, '.' ) 函数来截取文件名中最后一个 . 后面的字符,来识别为上传的文件的后缀名,并只接受后缀名为 jpgjpegpng 的文件。同时使用了 getimagesize( $uploaded_tmp ) 来获取文件头中的图片尺寸信息,读取不到尺寸信息则拒绝上传。

此时只能使用图片马:

windows

1
copy huaji.gif /b + shell.php /a shell.gif

Linux

1
cat huaji.jpg shell.php > shell.jpg

图片马需要通过命令注入漏洞rename shell.jpg shell.php来把上一步上传的 shell.jpg 重命名为 shell.php,然后利用文件包含漏洞才能执行,使用include包含。

include 方法可以让当前页面去执行指定的另外一个文件中的代码内容。

存在如下文件:upload/include.php,文件内容如下:

1
2
3
4
<?php
$file = $_GET['page'] ;
include ($file);
?>

使用localhost:8080/upload/include.php?page=shell.php可以借助蚁剑连接成功。

16. php内置函数获取图片类型

比如getimagesize()、exif_imagetype()。

exif_imagetype() 读取一个图像的第一个字节并检查其签名。

exif_imagetype环境需要开启php_exit模块。如果函数出现报错,则需要去php.ini修改如下内容:

1
2
extension=php_mbstring.dll
extension=php_exif.dll

然后再重启服务器即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
header("Content-Type: text/html;charset=utf-8"); //设置编码为UTF-8 不然乱码
$filename = $_GET['filename']; //通过get传值判断文件类型
$image_type = exif_imagetype($filename);
echo "进行判断";
switch ($image_type){
case IMAGETYPE_GIF:
echo $filename."文件类型:GIF";
break;
case IMAGETYPE_JPEG:
echo $filename."文件类型:jpg";
break;
case IMAGETYPE_PNG:
echo $filename."文件类型:png";
break;
default:
echo $filename."文件类型:未知";
break;
}
?>

上图片马绕过。

17. 上传后重命名(md5)

使用了 md5() 函数对上传的文件的文件名进行重命名,重命名为 MD5 散列运算之后的值。可以防御通过 00 截断来解析一句话木马。同时使用了随机 Token 检查来增加修改数据包上传的难度。

img

18. 竞争条件攻击

参考upload-labs Pass-18。

一些网站上传文件的逻辑是先允许上传任意文件,然后检查上传的文件是否包含WebShel脚本,如果包含则删除该文件。这里存在的问题是文件上传成功后和删除文件之间存在一个短的时间差(因为要执行检查文件和删除文件的操作) , 攻击者就可以利用这个时间差完成竞争条件的上传漏洞攻击。

19. ==数据溢出==

php文件被安全狗拦截:

image.png

修改数据包上传Content-Disposition: form-data; name="uploadfile";中间插入大量的垃圾数据从而绕过。

image.png

20. 站库分离

文件和网站放在不同的服务器上,即单独设置文件服务器的域名。这样就无法通过上传的文件对网站服务器进行渗透。

IIS解析漏洞

IIS6.0文件解析漏洞

  1. IIS除了可以解析.asp后缀的脚本以外,还可以解析.cer和.asa后缀的文件
  2. 特殊符号“/”,任意文件夹名.asp目录下的任何文件都会被IIS当作asp脚本执行
  3. 特殊符号“;”,任意文件名.asp;.jpg,后缀是.jpg,可以绕过限制,但是IIS6.0的特殊符号“;”会将该文件当作asp脚本执行
    IIS7.5文件解析漏洞
    任意文件名/任意文件名.php,解析为php脚本文件。

Apache解析漏洞

Apache httpd 多后缀解析漏洞

主要是因为Apache默认一个文件可以有多个用.分割得后缀,当最右边的后缀无法识别(mime.types文件中的为合法后缀)则继续向左看,直到碰到合法后缀才进行解析(以最后一个合法后缀为准)

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

影响范围:2.4.0-2.4.29版本

原因:合法后缀配置文件中的正则表达式中$不仅匹配字符串结尾位置,还可以匹配\n或\r,在解析php时,1.php\x0A将按照.php进行解析,而’.php\x0A’ != ‘.php’,可能过滤时过滤了.php但没有过滤.php\x0A从而实现绕过。

Nginx解析漏洞

任意文件名/任意文件名.php,解析为php脚本文件。