从dotnet源码看⽂件上传绕waf
字数 1227 2025-08-29 08:31:35
ASP.NET 文件上传 WAF 绕过技术分析
1. 前言
本文基于对 ASP.NET 核心文件上传处理机制的源码分析,揭示了几种可用于绕过 Web 应用防火墙(WAF)的文件上传技术。这些技术主要利用了 ASP.NET 对 HTTP 请求头解析的特殊处理方式。
2. 环境搭建
示例代码展示了一个典型的 ASP.NET 文件上传处理端点:
public ActionResult Index() {
if (Request.Files.Count > 0) {
var file = Request.Files[0];
var filename = file.FileName;
var contenttype = file.ContentType;
var reader = new StreamReader(file.InputStream);
var content = reader.ReadToEnd();
var filepath = Request.MapPath("~/") + filename;
file.SaveAs(filepath);
var resp = $"filename:{filename}\n save file path:{filepath}\n file content:{content}\n file content type:{contenttype}";
return Content(resp);
} else {
return Content("no file");
}
}
3. 核心处理流程分析
文件上传处理的核心类位于 System.Web.HttpMultipartContentTemplateParser.Parse() 函数:
internal static MultipartContentElement[] Parse(HttpRawUploadedContent data, int length, byte[] boundary, Encoding encoding) {
HttpMultipartContentTemplateParser httpMultipartContentTemplateParser = new HttpMultipartContentTemplateParser(data, length, boundary, encoding);
httpMultipartContentTemplateParser.ParseIntoElementList();
return (MultipartContentElement[])httpMultipartContentTemplateParser._elements.ToArray(typeof(MultipartContentElement));
}
调用层级关系为:
Request.Files → FillInFilesCollection() → GetMultipartContent() → Parse()
4. 关键绕过技术
4.1 Content-Type 头绕过
在 FillInFilesCollection() 中,content-type 必须以 multipart/form-data 开头,但有以下特性:
- 可以使用 Unicode 空白字符(如
\u0085)作为分隔符 - 可以添加任意参数
有效构造示例:
Content-Type: multipart/form-data\u0085,boundary=aaa
4.2 Boundary 提取机制
GetMultipartBoundary() 函数处理 boundary 参数:
private byte[] GetMultipartBoundary() {
string text = HttpRequest.GetAttributeFromHeader(this.ContentType, "boundary");
if (text == null) {
return null;
}
text = "--" + text;
return Encoding.ASCII.GetBytes(text.ToCharArray());
}
GetAttributeFromHeader 是关键函数,它:
- 使用分号、逗号和等号作为分隔符
- 根据字符集忽略一些空白字符
4.3 Content-Disposition 头绕过
ParsePartHeaders 函数解析 Content-Disposition 和 Content-Type 头:
- 先以冒号分割,取冒号后的部分
ExtractValueFromContentDispositionHeader函数会自动加上分号和等号
有效构造示例:
Content-Disposition:\u0;asdas\u0085d;085filename=11.aspx
Content-Disposition:filename=11.aspx
Content-Disposition:aaaaaaaaaaafilename=11.aspx;aaaaaaaaa
关键特性:
form-data字段可以省略- 可以在
filename和name前随意填充字段 filename和name后必须跟随等号- 末尾可以有分号标识结束
- 可以使用 Unicode 空白字符(如
\u0085),通常放在两侧会被Trim()去除
4.4 Name 字段处理
Request.Files[0] 的 name 字段处理特性:
- 忽略大小写
Request.Files[0]和Request.Files["file"]两种写法在绕过时可能有差异
5. 完整绕过示例
一个构造的完整请求示例可能包含以下特征:
- 使用特殊空白字符分隔头字段
- 在关键字段前添加干扰字符
- 省略非必要字段
- 使用 Unicode 字符干扰解析
6. 防御建议
- 严格验证
Content-Type头格式 - 对文件名进行严格的白名单验证
- 处理前规范化所有头字段,去除特殊字符
- 实现多层次的防御机制,而不仅依赖 WAF
- 关注 ASP.NET 安全更新,及时修补解析漏洞
通过理解这些绕过技术的原理,开发人员和安全工程师可以更好地设计防御策略,防止恶意文件上传攻击。