一、什么是文件上传漏洞
应用程序存在文件上传功能点,但是后台对用户上传的文件没有进行任何的安全校验或者校验机制不够严谨,导致攻击者可以上传恶意文件(Webshell、病毒)到服务器,进而执行恶意代码、获取服务器权限或进行其他恶意操作。
二、常见安全机制及绕过
为防御文件上传漏洞,开发者通常会实施以下检查:
1-客户端检查
许多开发者为了方便,使用JavaScript在浏览器校验文件类型,如.jpg、.png、.gif等。这种安全机制能减轻服务器压力,但是容易被绕过
常见绕过方法:
(1)禁用JavaScript
这是最直接的方法,在浏览器设置中直接禁用JS,能够直接关闭客户端检查,上传恶意文件
操作步骤:
-
先尝试上传php文件,浏览器弹窗不允许上传

-
判断是客户端检查,直接在浏览器
禁用JavaScript

-
成功上传,执行命令

2-抓包再修改文件名
我们上传一个合法文件绕过客户端检查,burpsuite拦截数据包修改文件名为.php后缀。由于服务器后端没有二次验证,就会直接上传成功
-
我们将
.php文件修改为.jpg,正常上传一个合法文件

-
burpsuite拦截数据包,修改文件名

-
上传成功,回显phpinfo界面

2-MIME类型检测
服务器有时会通过检查HTTP请求头中的Content-Type字段来验证文件类型。例如,一个图片的Conent-Type字段为image/jpeg或image/png
绕过方法:
(1)修改Content-Type
上传一个.php文件,同时使用burpsuite拦截数据包,看到Content-Type为application/octet-stream

将其修改为image/jpeg或image/png

成功上传

3-文件内容检查
- 检查文件头(Magic Number)是否匹配预期类型(如图片的
FF D8 FF)。 - 使用函数如
getimagesize()验证图片有效性。 - 使用
exif_imagetype()检查是否为图片文件。
绕过方法
(1)伪造文件头
在文件开头添加预期格式的幻数(如GIF89a),使内容检查误判为GIF。

上传成功,访问链接为/upload/6420260312145040.gif,配合文件包含漏洞解析

(2)图片马绕过
使用工具将恶意代码附加到合法图片末尾,仍能通过getimagesize()等检查。
操作步骤:
-
准备一张正常的图片(1.jpg)和一个包含恶意代码的文本文件(shell.php)
-
使用cmd命令将两者合并:
copy /b 1.jpg shell.php webshell.jpg

-
上传文件,复制图片路径,配合
文件包含漏洞来解析我们上传的图片马

图片马的制作方法:
-
文本方式打开图片直接粘贴一句话木马:将一个图片以文本格式打开(这里用的记事本方式打开修改,不过修改后图片无法正常显示了),后面粘贴上一句话木马

-
cmd 命令行执行:在windows的cmd中执行,准备好一个jpg 图片 和一个 有恶意代码的php文件,执行命令

-
用
16进制编辑器打开图片,在末尾添加恶意代码:用winhex 打开图片,添加一句话木马 保存成功

4-文件扩展名黑名单
服务器通常会有一份黑名单或白名单来限制可上传的文件扩展名。
- 黑名单 是禁止上传危险扩展名,如:
.php、.asp、.jsp

(1)大小写绕过
原理 :未统一转换为小写,允许大小写混合绕过
上传一个shell.php恶意文件,我们可以使用大小写混淆的方法修改文件扩展名来绕过黑名单
shell.Php
shell.pHp
shell.PHp
组合不止这些,可以自行补全
(2)特殊扩展名
某些服务器或脚本引擎支持非标准的扩展名,例如:
- PHP:
.php3、.php4、.php5、.phtml、.php7、.phps(可能泄露源码)、.php-s等。 - ASP:
.asp、.aspx、.cer、.asa、.cdx。 - JSP:
.jsp、.jspx、.jspf。 - Perl:
.pl、.cgi。
如果黑名单只列出了常见的.php、.asp,而忽略了这些变体,攻击者可以利用它们上传可执行脚本。

成功上传
(3)%00截断漏洞
此漏洞存在于PHP 5.3.4之前版本且magic_quotes_gpc关闭时。
攻击者在文件名后插入空字节(URL编码为%00),导致服务器在C语言级别处理文件名时截断后续内容。
- 上传
shell.php%00.jpg - 服务器解析时为:
shell.php - 文件系统保存为:
shell.php
(4).htaccess 绕过
若允许上传.htaccess文件,可重写配置使图片文件被当作脚本解析。内容如下
AddType application/x-httpd-php .png
- 攻击者上传:
.htaccess - 上传
shell.png即可执行。
(5)双写后缀
如果过滤逻辑只是简单地将php字符串替换为空,双写会导致过滤后剩下php。
shell.pphphp
(6)利用文件系统特性
如果目标站点是Windows系统,可以利用文件系统的特性尝试绕过
- 点绕过 :在Windows系统中,文件后缀名的最后一个点会自动去除,例如上传
shell.php.(末尾带点),保存后可能变成shell.php; - 空格绕过 :Windows系统也会自动去除文件名末尾的空格。例如,上传
shell.php(末尾有空格),保存后变为shell.php,同样可能绕过黑名单检查。 - 点绕过和空格绕过结合 :
a.php .一些黑名单实现可能只检查最后一个点之后的字符串,但遇到点和空格组合时,可能因空格而导致解析异常(如php.被当作普通字符串),从而绕过检测。 - ::data 绕过:在普通情况下,我们使用的文件只有一个默认的数据流,可以通过文件名访问。但是,在windows NT文件系统(NTFS)支持在文件内部创建额外的数据流,以存储其他信息。这些额外的数据流可以通过在文件名后面添加
::$DATA来访问。

(7)双重扩展名绕过
双重扩展名(double extension),即文件名包含两个或多个点,如shell.php.jpg。双重扩展名绕过能否成功取决于两个阶段的不匹配:
-
过滤阶段:仅检查最后一个扩展名,忽略了前面的危险扩展名。
-
执行阶段 :服务器或应用解析文件时,考虑了文件名中的其他部分,导致恶意代码被执行。
模拟情景:1.我们上传一个shell.php.jpg
2.校验机制只检查最后一个扩展名.jpg,成功上传文件到服务器
3.某些Web服务器(如Apache的mod_mime模块)可能根据扩展名的出现顺序决定内容类型。若第一个扩展名(如.php)被识别为可执行脚本,而后续扩展名被忽略,则文件可能被解析为PHP。
4.shell.php.jpg成功被解析为php文件执行
5-文件扩展名白名单
白名单 是允许上传安全扩展名,如:.jpg、.png等
(1)服务器解析漏洞
Apache
如果Apache的mime.types配置错误或开启了MultiViews,可能导致文件名如test.php.jpg被当作PHP解析(服务器可能从左至右匹配MIME类型,若第一个扩展名无法识别则尝试后续)。
IIS 6.0
目录解析漏洞,例如/xx.asp/shell.jpg,服务器会把shell.jpg当作ASP脚本执行
IIS 7.0/7.5
web.config配置文件解析漏洞。攻击者可以上传一个恶意的web.config文件来改变目录的解析规则
(2)竞争条件
一些服务器在处理文件是,会将文件临时保存,然后进行安全检查,最后再重命名或移动到目录
利用方法: 攻击者可以利用这个时间差,在文件被检查并删除之前迅速访问该文件
步骤:
- 上传个包含恶意代码的文件,其中恶意代码会创建一个新的Webshell文件
- 在文件上传成功后,但在服务器删除它之前,通过个脚本循环快速访问该文件
- 恶意文件被执行,并创建一个新的、无法被删除的Webshell文件
(3)配合文件包含漏洞
如果应用存在本地文件包含(LFI)漏洞,攻击者可上传一个扩展名安全的文件(如.jpg),但其内容包含PHP代码。随后通过LFI漏洞包含该文件,触发代码执行。
- 利用方法: 上传
shell.jpg,内容为<?php phpinfo(); ?>,并通过LFI访问/includes/index.php?page=uploads/shell.jpg(假设LFI可包含任意文件)。 - 条件:应用中存在LFI漏洞,且上传目录在包含路径内。
(4)%00截断存储路径
%00截断(Null Byte Injection) 这是一个经典的漏洞,主要影响PHP 5.3.4之前的版本。
- 条件: 服务端代码拼接文件路径和文件名,且路径信息可控。
- 步骤:
- 上传个包含恶意代码的
shell.png,拦截数据包 - 如果在数据包中存储路径可控,将
path=../uploads/修改为path=../uploads/shell.php%00 - 发送数据包到服务器
- 上传个包含恶意代码的
- 执行过程 :
- 服务端拼接出的最终保存路径是
../uploads/shell.php%00image.jpg。 - 在C/C++等底层语言中,字符串以空字节(\0)作为结束符。
- move_uploaded_file()函数在处理这个路径时,遇到空字节就认为路径已经结束,后面的image.jpg被忽略。
- 最终,文件被保存为
../uploads/shell.php,成功绕过了白名单对.jpg后缀的检查。
- 服务端拼接出的最终保存路径是