文件操作漏洞总结

本文总结文件操作漏洞(文件上传、文件包含、文件读取、目录穿越等)漏洞原理、利用方式及防御方法...

本文涉及内容,仅限于网络安全从业者学习交流,切勿用于非法用途…

0x01 文件上传漏洞

1. 漏洞简介

File upload(任意文件上传漏洞),Web 应用程序在处理用户上传的文件时,没有判断文件的扩展名或文件类型是否在允许的范围内,就把文件保存在服务器上,导致恶意用户可以上传任意文件,甚至上传脚本木马到web 服务器上,直接控制 web 服务器。

a. 攻击场景

1
2
3
4
5
6
7
8
9
(1) 上传文件是Web脚本语言,Web服务器解释并执行了用户上传的脚本,导致代码执行

(2) 上传文件是病毒或者木马时,可用于诱骗用户或者管理员下载执行或者直接自动运行

(3) 上传文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为

(4) 上传文件是钓鱼图片或包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈

(5) 上传一个合法的文本文件,其内容包含了PHP脚本,再通过"本地文件包含漏洞(Local File Include)"执行此脚本

b. 利用条件

1
2
3
4
5
(1) 上传的文件能够被Web容器解释执行,文件上传后所在的目录需是Web容器所覆盖到的路径

(2) 上传的文件能够从Web上访问

(3) 上传的文件未被安全检查、格式化、图片压缩等功能改变内容

c. 漏洞类型

1
2
3
4
5
6
7
8
9
10
11
1.服务器配置不当

2.开源编辑器上传漏洞

3.本地文件上传限制被绕过

4.过滤不严或被绕过

5.文件解析漏洞导致文件执行

6.文件路径截断

2. 绕过姿势

a. 客户端绕过

1
2
3
4
5
6
7
1. 通过火狐插件NOscript插件或者禁用IE中JS脚本

2. 通过firbug插件元素审核修改代码(如删除onsubm:t="return checkFile()"事件)

3. 通过firbug元素审核javascirpt脚本中添加上传文件类型

4. 通过利用burp抓包改包,先上传一个gif类型的木马,然后通过burp将其改为asp/php/jsp后缀名,请求头中的Content-Length的值也要修改

b. 服务端绕过

(1) 黑名单扩展名绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1) 利用黑名单未包含的扩展名进行绕过:如iis6.0中的asa 和cer,

2) 黑名单特殊后缀名绕过:pht, phpt, phtml, php3,php4,php5,php6,需满足http.conf中设置AddTypeapplication/x-httpd-php .php1(php的版本小于等于5.3.29以下)


2)利用可能存在大小写绕过漏洞:如aSp(iis6.0中)和pHp(能在小于php5.3.39中的linux中)

3)利用能被WEB容器解析的文件其他扩展名列表绕过

jsp,jspx ,jspfasp

asa cer cdx,htr,xml,html

aspx,ashx,asmx,asax,ascx

(2) 利用系统文件命名规则绕过

1
2
3
4
1) windows系统下,如果文件名以"."或者空格作为结尾,系统会自动删除"."不空格,利用此特性也可以绕过黑名单验证;apache中可以利用点结尾和空格绕过,asp和aspx中可以用空格绕过

2)linux中当php版本小于php5.3.39,可用pHp大小写绕过

(3) 服务端MIME文件类型(Content-Type)绕过

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
1)MIME作用

使客户端软件,区分不同种类的数据,例如web浏览器就是通过MIME类型来判断文件是GIF图片,还是可打印的PostScript文件。web服务器使用MIME来说明发送数据的种类,web客户端使用MIME来说明希望接收到的数据种类,它是服务器用来判断浏览器传递文件格式癿重要标记项

2)常用文件上传类型的MIME表:

text/plain(纯文本)
text/html(HTML文档)
text/javascript(js代码)
application/xhtml+xml(XHTML文档)
image/gif(GIF图像)
image/jpeg(JPEG图像)
image/png(PNG图像)
video/mpeg(MPEG动画)
application/octet-stream(二进制数据)
application/pdf(PDF文档)
application/(编程语言) 该种语言的代码
application/msword(Microsoft Word文件)
message/rfc822(RFC 822形式)
multipart/alternative(HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示)
application/x-www-form-urlencoded(POST方法提交癿表单)multipart/form-data(POST提交时伴随文件上传的表单)

3)绕过方法

上传对文件类型做了限制,可通过burpsuit将其他类文件类型修改为如:Content-Type:image/gif和image/jpeg等运行的文件类型

(4) 利用文件包含漏洞绕过

1
2
3
4
5
6
7
8
9
10
11
12
13
1) 运行上传文件包含脚本木马和一句话木马

前提:校验规则只校验当文件后缀名为asp/php/jsp癿文件内容是否为木马

(a) 先上传一个内容为木马癿txt后缀文件,因为后缀名的关系没有检验内容;

(b) 然后再上传一个.php的文件,内容为<?php Include("上传的txt文件路径");?>

此时,这个php文件就会去引用txt文件的内容,从而绕过校验

(2) 存在本地文件包含漏洞,并可上传一句话内容马

上传一个符合条件格式的文档,文档内容为一句话木马,利用文件包含漏洞包含上传癿木马文件

c. 白名单绕过

(1) 利用web服务器解析漏洞

1
2
3
4
5
6
7
1) nginx空字节漏洞

xxx.jpg%00.php 这样的文件名会被解析为php代码运行

2)apache解析漏洞

上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别癿,因此就会直接将类型识别为php,从而达到注入php代码的目的

(2) .htaccess 文件重写绕过

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

配合黑名单列表绕过,上传一个自定义的.htaccess和一句话图片木马,可绕过各种检测

(3) 文件头检测绕过

1
2
3
4
5
6
7
文件头过滤主要是通过验证图片的文件头的方式来判断是不是图片文件,针对这种情况,在要上传文件的文件头里面加上图片文件头即可绕过;如图片文件是否文件头含有gif89,可以通过一句话图片木马生成工具edjpgcom或者通过编辑器在木马内容基础上再加一些文件信息

不同的图片文件都有不同文件头,如:

PNG:文件头标识(8 bytes) 89 50 4E 47 0D 0A 1A 0A
JPEG:文件头标识(2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识)
GIF:文件头标识(6 bytes) 4749 46 38 39(37) 61

(4) CMS、编辑器漏洞绕过CMS漏洞

1
2
3
4

针对不同CMS存在的上传漏洞进行绕过

编辑器漏洞:如FCK,Ewebeditor等,可以针对编辑器的漏洞进行绕过

(5) 对渲染/加载测试攻击内容检查绕过

通过向图片中加入代码注入,这里一般为一句话图片木马,可能正常访问图片

d. WAF绕过

(1) WAF检查的位置

1
2
3
4
5
6
7
8
9
10
11
文件名:解析文件名,判断是否在黑名单内

文件内容:解析文件内容,判断是否为webshell

文件目录权限

请求的url

Boundary边界

MIME文件类型

(2) 绕过WAF方法

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
1) 填充垃圾数据绕过

有些主机WAF软件会对校验的用户数据设置大小上限,此种情况可以构造一个大文件,在木马内容前填充垃圾内容,可以绕过WAF对文件内容的校验; 可在Content-Type类型数据后添加垃圾数据,也可以将垃圾数据放在数据包最开头、绕过对文件名的校验

2) POST/GET的更改方法绕过

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

3) 删除实体里面的Conten-Type字段绕过

4) 删除Content-Disposition字段里的空格绕过

5) 修改Content-Disposition字段值的大小写绕过

6) 文件扩展名出回车绕过(只支持php)

7) 利用NTFS ADS特性绕过

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

8) 文件重命名绕过

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

9) 特殊的长文件名绕过

文件名使用非字母数字,比如中文等最大程度的拉长

10) 引号去掉,双引号变单引号绕过

11) 删除Content-Disposition值的form-data绕过

12) 多个分号绕过

当WAF遇到name="myfile";;时,认为没有解析到filename。而后端容器继续解析到的文件名是bk.php,导致WAF被绕过

13) name和filename添加任意字符串(长度大于等于508)

14) head头的content-type:tab绕过

15) head头的content-type: multipart/form-data改成大写绕过

16) head头的Content-Type: multipart/form-data;\n绕过

3. 防御及修复

当一个文件以HTTP协议进行上传时,将以POST请求发送至Web服务器,Web服务器接收到请求并同意后,用户与Web服务器将建立连接,并传输数据,针对文件上传过程检测校验措施如下:

a. 客户端校验

1
通过javascript来校验上传文件的后缀是否合法,可以采用白名单/黑名单的方式;在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包

b. 服务端校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1) 文件头content-type字段校验(image/gif)

2) 文件内容头校验,通过正则匹配来判断文件幻数(文件头)内容是否符合要求,常见的文件头(文件头标志位)如下:

a) .JPEG;.JPE;.JPG,"JPGGraphicFile"(FFD8FFFE00)

b).gif,"GIF89A"(474946383961)

c).zip,"ZipCompressed"(504B0304)

d).doc;.xls;.xlt;.ppt;.apr,"MSCompoundDocumentv1orLotusApproachAPRfile"(D0CF11E0A1B11AE1

3)目录路经检测(检测跟Path参数相关的内容)

4)文件扩展名检测(检测跟文件extension 相关的内容)

5)后缀名黑名单校验

6)后缀名白名单校验

7)自定义正则校验

c. WAF拦截

使用不同的WAF产品来进行过滤,通常是独立于服务程序的一段中间程序或者硬件

d. 漏洞修复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(1) 将文件上传的目录设置为不可执行:只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响

(3) 文件类型检查(白名单)

在判断文件类型时,可以结合使用MIME Type、后缀检查等方式,在文件类型检查中,推荐白名单方式;此外对于图片的处理可使用压缩函数或resize函数,处理图片的同时破坏其包含的HTML代码

(4) 改写文件名和文件路径

文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本

(4) 本地文件上传限制被绕过:在服务器后端对上传的文件进行过滤

(5) 单独设置文件服务器的域名

由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml、上传包含Javascript癿XSS利用等问题将得到解决

(6) 开源编辑器上传漏洞

更新编辑器版本,修复已知漏洞

0x02 文件读取漏洞

任意文件读取是属于文件操作漏洞的一种,任意文件读取漏洞可以读取配置信息甚至系统重要文件。

1. 敏感文件

用户目录下的敏感文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.bash_history
.zsh_history
.profile
.bashrc
.gitconfig
.viminfo
/etc/passwd
/etc/hosts
/etc/group
/etc/shadow
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_rsa.keystore
/root/.ssh/known_hosts

应用的配置文件

1
2
3
4
5
6
/etc/apache2/apache2.conf
/etc/nginx/nginx.conf
/.htaccess
/phpinfo.php
/inc/db.php
/inc/conn.php

应用的日志文件

1
2
/var/log/apache2/access.log
/var/log/nginx/access.log

站点目录下的敏感文件

1
2
3
4
.svn/entries
.git/HEAD
WEB-INF/web.xml
.htaccess

特殊的备份文件

1
2
3
4
.swp
.swo
.bak
index.php~

Python的Cache

1
__pycache__\__init__.cpython-35.pyc

2. 文件读取函数

readfile()、file_get_contents()、fopen()中,$filename没有经过校验或者校验不合格,用户可控制变量读取任意文件

0x03 文件包含漏洞

为了更好地使用代码的重用性,引入了文件包含函数,通过文件包含函数将文件包含进来,直接使用包含文件的代码。

1. 漏洞成因

文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。

2. PHP危险函数

1
2
3
4
5
6
7
8
include()
include_once()
require()
require_once()

include()如果在包含过程中出错,只会提出警告,但不影响后续语句的执行
require()如果在包含过程中出错,就会直接退出,不执行后续语句
require_once() 和 include_once() 功能与require() 和 include() 类似。但如果一个文件已经被包含过了,则 require_once() 和 include_once() 则不会再包含它,以避免函数重定义或变量重赋值等问题

3. 漏洞分类

本地文件包含漏洞(LFI)

指能打开并包含本地文件的漏洞,较为普遍。

文件包含可以包含任意文件,如图片,文本文件,压缩包等等,如果文件中有服务器能识别的脚本语言,就按照当前脚本语言执行,否则就直接显示出源代码。

远程文件包含漏洞(RFI)

指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在,危害性会很大。

利用条件较苛刻,需要php.ini中配置:

1
2
allow_url_fopen=On
allow_url_include=On

4. PHP伪协议

PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数。 除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
file:// — 访问本地文件系统

http:// — 访问 HTTP(s) 网址

ftp:// — 访问 FTP(s) URLs

php:// — 访问各个输入/输出流(I/O streams)
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。

zlib:// — 压缩流

data:// — 数据(RFC 2397)

glob:// — 查找匹配的文件路径模式

phar:// — PHP 归档

ssh2:// — Secure Shell 2

rar:// — RAR

ogg:// — 音频流

expect:// — 处理交互式的流

a. php://filter

利用条件:

只是读取,所以需要开启allow_url_fopen,对 allow_url_include不做要求

用法:

1
index.php?file=php://filter/read=convert.base64-encode/resource=xxx.php

通过指定末尾文件,可以读取经base64加密后的文件源码,能够读取敏感文件

b. php://input

可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行

利用条件:

需要开启allow_url_include=on,对allow_url_fopen不做要求

用法:?file=php://input 数据利用POST传过去,可以写入木马、命令执行

c. zip://伪协议

zip://可以访问压缩文件中的文件

条件: 使用zip协议,需要将#编码为%23,所以需要PHP 的版本> =5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23。

用法:?file=zip://[压缩文件路径]#[压缩文件内的子文件名]

d. phar://伪协议

与zip://协议类似,但用法不同,zip://伪协议中是用#把压缩文件路径和压缩文件的子文件名隔开,而phar://伪协议中是用/把压缩文件路径和压缩文件的子文件名隔开,即 file=phar://[压缩文件路径]/[压缩文件内的子文件名]

e. data:text/plain

和php伪协议的input类似,也可以执行任意代码,但利用条件和用法不同

条件:allow_url_fopen参数与allow_url_include都需开启

用法1:?file=data:text/plain,<?php 执行内容 ?>
用法2:?file=data:text/plain;base64,编码后的php代码

经base64编码后的加号和等号要手动的url编码

f. file://伪协议

file:// 用于访问本地文件系统,且不受allow_url_fopen与allow_url_include的影响。
用法:?file=file://文件绝对路径

5. 防御修复

1、PHP 中使用 open_basedir 配置限制访问在指定的区域
2、过滤.(点)/(反斜杠)\(反斜杠)等特殊字符
3、尽量关闭allow_url_include配置

0x04 目录穿越漏洞

1. 简介

目录穿越(目录遍历/directory traversal/path traversal)是通过使用 ../ 等目录控制序列或者文件的绝对路径来访问存储在文件系统上的任意文件和目录,攻击者可以利用该漏洞读取运行应用程序的服务器上的任意文件。

2. 攻击载荷

常用路径

1
2
3
4
5
6
7
8
9
10
11
12
/../../../../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../../../../../etc/passwd%00
../../../../../../../../../../etc/passwd
....//....//static/xx.php%00.png

../../../WEB-INF/web.xml #Java Web项目配置文件

# Tomcat
/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd

C:/boot.ini
C:\boot.ini

URL参数

1
2
3
../
..\
..;/

Nginx Off by Slash

1
https://vuln.site.com/files../

UNC Bypass

1
\\localhost\c$\windows\win.ini

3. 绕过方式

基础目录遍历

直接利用 ../ 返回上一级来遍历任意文件

1
../../../etc/passwd

绝对路径

web网站有时候会采取目录遍历的防御措施,如过滤 ../ 上一级等关键字,然后简单的过滤通常会被绕过。可以直接采用绝对路径,无须 ../ 返回上一级目录遍历

1
/etc/passwd

双写../绕过

遇到防御措施是直接将 ../ 替换为空的情况,可以直接采用双写直接绕过:

1
....//....//....///etc/passwd

绝对路径配合 ../

有些 web 在获取文件时,会首先判断是否以一个固定的路径开头,那么就可以配合 ../ 来返回上一级遍历任意文件

1
/var/www/html/../../../etc/passwd

截断文件后缀

某些 web 对文件类型作了限制,只有当后缀为图片时才解析,可以利用 %00 来截断

1
../../../etc/passwd%00.jpg

URL编码绕过

可以采用 URL 编码来绕过服务器对 . 或者 / 的检测

1
2
3
. => %2c
/ => %2f
% => %25 (双重URL编码)

16位Unicode编码

1
\u002e

超长UTF-8编码

1
\%e0%40%ae

0xFF Reference