为什么上传一张“图片”,最后却能控制服务器?——文件上传漏洞入门学习
最近学 Web 安全的时候,学到了一个很经典的漏洞:
文件上传漏洞(Upload Vulnerability)
刚开始看到这个名字的时候,我其实有点懵。
上传文件不是很正常吗?
头像、图片、附件、简历……
几乎所有网站都有上传功能。
那它为什么会变成漏洞?
后来真正理解之后,我发现:
文件上传漏洞,本质其实是“服务器错误地执行了用户上传的文件”。
今天这篇文章,就用我的逻辑和语言,聊聊我最近对文件上传漏洞的理解。
一、正常的网站为什么需要文件上传?
其实这个功能太常见了。
比如:
- 上传头像
- 上传图片
- 上传 PDF
- 上传 Word 文档
- 上传简历
- 上传视频
这些都属于:用户把文件传给服务器
比如你换微信头像。
本质上其实就是:POST /upload
浏览器把:
- 文件名
- 文件内容
- 文件类型
一起发送给服务器。
服务器收到之后:
正常来说,到这里都没有问题。
问题出现在:“服务器怎么检查这个文件”。
二、文件上传漏洞到底是什么?
网站把“用户上传的文件”,当成了“程序”执行。
这就危险了。
比如:
正常用户上传:1.jpg 没问题。
但攻击者上传:<?php phpinfo(); ?>
如果服务器把它当PHP 执行了。
那访问:/upload/test.php
页面就会执行代码。
这时候已经不是“上传文件”了。
而是:用户开始在服务器上运行代码。
这个危险程度其实非常高。
严重情况下:
- 可以控制网站
- 获取数据库
- 读取服务器文件
- 拿到 WebShell
- 甚至继续入侵内网
很多真实攻击,最开始就是一个文件上传漏洞。
三、服务器为什么会执行上传的文件?
这里是我最近真正想明白的地方。
以前我一直以为:“上传成功 = 漏洞成功”。
后来发现根本不是。
真正关键的是:服务器“怎么解析这个文件”。
比如:test.php 为什么它危险?
因为:服务器看到 .php 后缀后。
会认为:这是 PHP 程序
于是交给 PHP 解析器执行。
而:1.jpg
服务器会认为:这是图片
所以只会展示,不会执行。
因此:文件上传漏洞的本质,其实是“解析问题”。
这句话非常重要。
四、网站一般怎么防御?
正常网站肯定不会允许你直接上传 .php。
所以通常会做检查。
比如:
1. 检查后缀名
允许:
- .jpg
- .png
- .gif
禁止:
- .php
- .jsp
- .asp
这是最基础的。
2. 检查 Content-Type
比如:
Content-Type: image/jpeg
看起来像图片。
但这里其实可以伪造。
所以单独依赖这个并不安全。
3. 检查文件头
比如:
JPG 文件开头:FF D8 FF
PNG 文件开头:89 50 4E 47
服务器会看看:“你到底是不是真图片”。
4. 重新生成图片
这个是更安全的方式。
有些网站会:
- 重新压缩
- 重新绘制图片
这样即使你藏了恶意代码,也可能被“洗掉”。
5.环境加固
禁用危险函数,及时更新服务器补丁,阻断恶意文件执行条件
给大家看看真实环境下的包里面包含的这些内容:
五、为什么还会出现漏洞?
因为很多网站:检查做得不完整。
比如:只检查文件名。
攻击者就可能:1.php.jpg
或者:1.PHp
甚至:1.php%00.jpg
不同服务器、不同环境、不同解析规则,可能都会导致绕过。
这里也是文件上传真正复杂的地方。
因为:漏洞很多时候不是代码本身,而是服务器环境导致的。
比如:
- Apache
- Nginx
- IIS
解析方式都可能不同。
5.1任意文件的绕过方式(请在合法授权的靶机环境使用)
A.黑名单
1.双写绕过:
通过重复写入被过滤的后缀(如 “php” 被拦截时,用 “pphphp”,过滤后剩余 “php”),绕过简单的字符串替换校验。
2.大小写绕过:
利用服务器对大小写不敏感的特性(如 “PhP”“pHp”),避开对 “php” 等小写后缀的检测。
3.空格绕过:
在文件名后添加空格(如 “shell.php”),部分校验机制会忽略空格,而服务器保存时可能自动截断空格,导致恶意文件被解析。
4.点绕过:
在文件名中加入多个点(如 “shell.php.”“shell.php...”),绕过对后缀长度或格式的简单校验,服务器可能仅识别最后一个点前的内容。
5.变形绕过:
使用脚本引擎支持的其他后缀(如 php3、pht、phar 等),或修改文件 MIME 类型(如将 php 文件伪装成 text/plain),绕过对白名单后缀的检测。
6.特殊符号绕过:
利用 “::$DATA”(Windows 系统),使服务器忽略后缀后的内容(如 “shell.php::$DATA” 被当作 “shell.php” 解析)。
7..htaccess 文件攻击:
上传恶意.htaccess 文件,修改服务器配置(如将.jpg 文件解析为 php),使原本合法的文件类型被当作脚本执行。
8.分步上传绕过:
先上传 “php:.jpg” 等混合后缀文件,再上传 “.<<<” 等文件触发服务器解析漏洞,使恶意脚本被执行。
B.白名单
1.MIME 类型篡改:
白名单若仅校验 HTTP 请求中的 Content-Type 字段(如限制为 image/jpeg),攻击者可通过抓包工具将恶意文件(如.php)的 Content-Type 改为白名单内类型,直接绕过校验。
2.特殊符号截断:
利用 %00(URL 空字符)、0x00(二进制空字符)等截断符,构造 “shell.php%00.jpg” 这类文件名,服务器在处理时可能忽略截断符后的内容,将文件识别为.php 并解析执行。
六、我现在终于理解 WebShell 是什么了
以前经常听别人说:“传个一句话木马”,但我一直没真正理解,现在终于懂了。
本质其实就是:上传一个能被服务器执行的脚本文件。
比如:<?php eval($_POST['cmd']); ?>
如果服务器执行它。
攻击者就能远程控制网站。
当然这里只是学习原理。
真正环境中一定不能乱测试!!!
七、文件上传漏洞最重要的不是“技巧”
我现在感觉,很多人刚学文件上传。
特别喜欢记:
- 双写绕过
- 大小写绕过
- MIME 绕过
- 图片马
但其实:最重要的是理解“服务器为什么会执行文件”,这个才是核心。
因为你真正理解解析逻辑之后。
后面的:
- 文件包含
- 命令执行
- RCE
- 中间件漏洞
会突然通很多。
八、总结
今天学文件上传漏洞之后。
我最大的感受是:Web 安全很多时候不是“黑客魔法”,而是“程序错误地信任了用户输入”。
而文件上传漏洞。
本质其实就是:
这个阶段开始能感觉到 Web 安全开始越来越有意思了,后面会发一些各种漏洞的打靶场教程想学的小伙伴可以关注一下后续内容哦!