跳转到内容

IIS/Nginx 文件上传安全:阻断 upload-to-RCE

核验于 1 分钟阅读

校验上传、存到可执行根之外、在上传路径禁脚本执行,并防路径遍历。

测试环境Standard / Datacenter · 版本号 26100.33650 · x64
E1
版本号
26100.33650
版本
Standard / Datacenter
架构
x64
支持
文档(E1)
证据
E1官方文档
核验日期
2026-10-29
页面类型
任务

上传危险是三件事同时成立:

  1. 文件落在 IIS/Nginx 服务的路径;
  2. 服务器执行该扩展名(.php、.asp、.aspx、.cgi);
  3. 攻击者控制名字/内容。

至少破坏两个。最好存到 Web 根之外,通过受控处理器下载。

  • 扩展名和 MIME 白名单;不要只信 Content-Type。
  • 代理 + 应用都限制大小。
  • 存储名随机;原名只做元数据。
  • 能重编码图片就重编码;去 EXIF。
  • 业务允许就 AV/EDR 扫描。
  • 上传放站点根之外,或放无脚本处理器目录。
  • 下载用 Content-Disposition: attachment + 安全 content type。

拒绝/规范化:

  • ../、..\、编码 %2e%2e%2f、双重编码;
  • 绝对路径(C:\、\\server\share);
  • NUL 字节和 ADS(file.php::$DATA)。

不要只用 Path.Combine 拼用户输入;解析规范路径并确认仍在上传根之下。

上传目录去掉脚本处理器(示例是去掉全部 handler,按需保留静态):

<location path="uploads">
<system.webServer>
<handlers>
<clear />
</handlers>
</system.webServer>
</location>

<clear /> 后目录什么都不服务;通常应只移除 *.php/*.asp handler,而不是全部静态。用真实文件测。

再用请求过滤拒绝上传路径里的可执行扩展。

location ^~ /uploads/ {
add_header Content-Disposition "attachment";
try_files $uri =404;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
}

^~ 阻止正则 PHP location 匹配 /uploads/ 下的文件。没有它,shell.php 会被执行。try_files 挡 PATH_INFO 技巧。

  1. 传 .php/.aspx,请求;应 404/403,不执行。
  2. 传 ..%2fweb.config;应拒绝。
  3. 传正常图片;应 200 且类型正确。
  4. 应用池身份不能写站点根,只能写 uploads。

E1。实验室用了 PHP FastCGI 和 IIS,但没有做上传/RCE 测试;控制项是 Server 2025 的生产清单。

来源