首页/安全/漏洞与攻击面速查/文件上传漏洞防护
Web 漏洞原理与防护55 条

文件上传漏洞防护

文件上传的风险不在上传动作本身,而在文件被谁以什么权限解析或执行;防护组合为:类型白名单(扩展名加内容特征)、重命名存储、隔离目录、禁止解析执行。

漏洞与攻击面速查安全更新于 2026-10-13

文件上传风险是什么

文件上传的风险不在上传动作本身,而在文件被谁以什么权限解析或执行:上传目录被当作脚本解析、文件名被用于拼接路径、上传内容被其他系统当作可信输入处理,三点任一成立都可能把一次上传变成执行入口。实践中的防护要按层次叠加:扩展名与内容双重校验负责挡掉非法文件,重命名与存储隔离负责让文件无法被直接访问,服务器配置负责切断解析路径。只做其中一层,往往会被组合手法绕过。

基本信息

风险类别OWASP Top 10 2021 A05 安全配置错误与 A03 注入类;CWE-434
常见后果上传的脚本被解析执行、覆盖既有文件、作为跳板访问内网
校验层次扩展名白名单、内容特征校验、存储重命名、目录不可解析
服务端原则校验全部在服务端完成,前端校验只用于改善体验
存储原则独立目录或对象存储,文件名与路径均不使用用户输入
配套控制大小与数量限制、上传者鉴权、下载走鉴权代理

常见出问题的地方

  • 头像、附件与工单图片上传,只校验扩展名不校验内容
  • 编辑器与富文本上传接口,允许的扩展名列表过宽
  • 导入功能支持压缩包,解压时不校验文件名与路径
  • 上传目录放在站点根目录下且允许脚本解析
  • 文件名直接拼接进存储路径,出现目录穿越
  • 下载接口按文件 ID 直读存储路径,未做权限校验

服务端校验清单

服务端校验清单
1. 扩展名白名单(按业务需求列出,如 jpg/png/pdf)
2. 内容特征校验(图片解码验证、文件头魔数)
3. 重命名存储(UUID + 固定扩展名),不使用用户文件名
4. 存储目录禁止解析执行(服务器配置层)
5. 大小与数量限制,防止资源耗尽
6. 下载与预览走鉴权代理,不直接暴露存储地址
# 白名单比黑名单可靠:不能枚举的语言与扩展名组合太多
# 校验顺序:先鉴权,再限大小,然后校验类型,最后重命名落盘

图片内容校验示意(Python Pillow)

图片内容校验示意(Python Pillow)
from PIL import Image
img = Image.open(path)
img.verify()                                   # 校验是否为有效图片
if img.format not in ('JPEG', 'PNG', 'WEBP'):
    raise ValueError('unsupported image format')

# 校验通过后统一重命名并按类型分目录存放
# 注意:解析库本身要定期更新,历史版本存在解析相关的漏洞

校验层次与作用

层次手段能防住什么
文件名层扩展名白名单、重命名伪装扩展名与特殊字符路径
内容层魔数校验、解码验证内容与扩展名不符的文件
存储层独立目录、不可解析、随机名直接访问与非授权下载
服务层鉴权、限大小与频率滥用上传接口与资源耗尽
运行层最小权限运行、容器隔离解析漏洞被利用后的影响范围
MIME 类型(Content-Type)由客户端提供、可伪造,只能作为辅助信号,不能作为唯一依据。
上传目录的处理方式要与部署形态匹配:动态站点要确保该目录不解析脚本,静态站点要确保不会被当作源码或配置读取,对象存储则要检查桶的读权限与临时链接有效期。

易错点

  • 只查扩展名不查内容:图片文件中混入脚本内容可绕过扩展名检查
  • 上传目录放在 Web 根目录且允许解析:任何解析差异都会直接变成执行入口
  • 使用用户提供的文件名落盘:可能造成覆盖既有文件或目录穿越,应重命名为随机串
  • 白名单过宽或包含压缩包:解压与二次处理环节会引入新的路径与权限问题
  • 下载接口不做鉴权:上传内容即使安全,也可能被他人在未授权情况下批量获取
  • 忽略解析库自身版本:图片与文档处理库的历史漏洞同样可被构造文件触发

数据来源与参考

  • OWASP File Upload Cheat Sheet
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌