跳转至

文件上传漏洞

文件上传漏洞的本质:服务器没有严格校验上传文件的类型,导致攻击者可以上传 Webshell(.php、.jsp、.asp 等脚本文件)并执行。


前端绕过

前端校验就是个纸老虎,全靠浏览器端的 JavaScript 检查,绕过方式很多:

  • 删除浏览器事件 — 直接在 DOM 里删掉 onsubmitonchange 的校验函数
  • Burp 抓包改后缀 — 先把文件改成 .jpg 通过前端,Burp 里再把后缀改回 .php
  • 构造本地表单 — 自己写一个不带校验的 HTML 表单,直接提交到上传接口
  • 禁用 JS — Chrome DevTools → Settings → Debugger → 勾选 Disable JavaScript

后端绕过

后端校验才是真正的防线,但实现得不好一样能绕。

黑名单绕过

黑名单的思路是"禁止 .php、.jsp 这些危险后缀",但总有漏网之鱼:

特殊后缀名

有些后缀名不在黑名单里,但服务器照样当代码执行:

语言 可尝试的后缀
PHP .php3 .php5 .phtml .pht .phps
ASP .asa .cer .cdx
JSP .jspx .jspf

前提条件:Apache 配置了这些后缀的处理器,比如:

# 如果有这行配置,上面那些后缀都能当 PHP 执行
AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml

# 修复方式:只保留 .php
AddHandler application/x-httpd-php .php

大小写绕过

Windows 不区分大小写,.PhP.pHp 都能被当 PHP 执行,但黑名单可能只禁了小写的 .php

双写绕过

如果后端只做了一次替换(把 php 替换为空),可以用 .pphphp — 替换后变成 .php

点和空格绕过(Windows)

Windows 会自动去掉文件名末尾的点和空格:

  • shell.php. → 保存为 shell.php
  • shell.php → 保存为 shell.php
  • shell.php::$DATA → NTFS 数据流,保存为 shell.php

.htaccess 绕过

如果能上传 .htaccess,就能让任意后缀被当 PHP 执行:

AddType application/x-httpd-php .jpg

上传这个 .htaccess 后,再上传一个 .jpg 的 Webshell 就能执行了。

白名单绕过

白名单比黑名单安全得多,但也不是绝对的:

%00 截断

PHP < 5.3.4 且 magic_quotes_gpc = Off 时有效:

文件名:shell.php%00.jpg
保存时:shell.php(%00 后面被截断)

解析漏洞

不同 Web 服务器的解析特性可以利用:

服务器 解析漏洞 示例
Apache 从右往左解析后缀,遇到不认识的继续往左 shell.php.xxx → 当 PHP 执行
IIS 6.0 分号截断 shell.asp;.jpg → 当 ASP 执行
IIS 6.0 目录解析 /shell.asp/1.jpg → 当 ASP 执行
Nginx 路径解析(配置不当时) /upload/1.jpg/1.php → 当 PHP 执行

MIME 类型绕过

如果只检查 Content-Type,Burp 里改成图片类型就行:

Content-Type: image/jpeg
Content-Type: image/png
Content-Type: image/gif

文件头绕过

如果检查文件内容的魔术字节(Magic Number),在 Webshell 前面加上图片文件头:

GIF89a<?php @eval($_POST['cmd']);?>

或者用 copy 命令把图片和 Webshell 合并:

copy /b image.jpg+shell.php shell.jpg

防御建议

措施 说明
白名单校验 只允许业务需要的文件类型
文件内容检查 校验 Magic Number,不能只看后缀和 MIME
重命名文件 用随机文件名,去掉原始后缀
存储隔离 上传目录不给执行权限,最好放对象存储(OSS)
独立域名 上传文件用单独域名提供访问,防止同域 Cookie 泄露