从dotnet源码看⽂件上传绕waf

admin 2025年6月15日02:24:55评论28 views字数 2879阅读9分35秒阅读模式

前言

看了赛博群的《从commons-fileupload源码看文件上传绕waf》,文末提到了dotnet也有这种问题,于是看了下dotnet的源码。

环境

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");
}
}

分析

对于上传的文件处理类位于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的层级调用关系如图

从dotnet源码看⽂件上传绕waf

在FillInFilesCollection()中,content-type必须以multipart/form-data开头

从dotnet源码看⽂件上传绕waf

这里和common fileupload的处理不同,然后进入this.GetMultipartContent()

从dotnet源码看⽂件上传绕waf

1来处理boundary 2来解析上传文件流 主要看1

private byte[] GetMultipartBoundary()
{
string text = HttpRequest.GetAttributeFromHeader(this.ContentType, "boundary");
if (text == null)
{
return null;
}
text = "--" + text;
return Encoding.ASCII.GetBytes(text.ToCharArray());
}

GetAttributeFromHeader是关键函数

从dotnet源码看⽂件上传绕waf

分号逗号和等于号作为分隔符,并根据字符集忽略一些空白字符

从dotnet源码看⽂件上传绕waf

所以content-type可以这么写

Content-Type: multipart/form-datau0085,;;,,,,,;;, boundary =   aaa

接着看GetMultipartContent函数,解析完boundary和文件内容流之后,进入3 Parse函数也就是我们开篇提到的函数。

从dotnet源码看⽂件上传绕waf

Parse函数就直接跟进了ParseIntoElementList函数

从dotnet源码看⽂件上传绕waf

其中1 ParsePartHeaders是关键函数

从dotnet源码看⽂件上传绕waf

能看到这个函数用来解析Content-DispositionContent-Type,先以冒号分割拿到冒号后的部分

Content-Disposition: form-data; name="file"; filename="1.txt"
Content-Type: text/plain

form-data; name="file"; filename="1.txt"

再看ExtractValueFromContentDispositionHeader函数

从dotnet源码看⽂件上传绕waf

string text = " " + name + "=";
int num = CultureInfo.InvariantCulture.CompareInfo.IndexOf(l, text, pos, CompareOptions.IgnoreCase);
if (num < 0)
{
text = ";" + name + "=";
num = CultureInfo.InvariantCulture.CompareInfo.IndexOf(l, text, pos, CompareOptions.IgnoreCase);
if (num < 0)
{
text = name + "=";
num = CultureInfo.InvariantCulture.CompareInfo.IndexOf(l, text, pos, CompareOptions.IgnoreCase);
}
}

会自动加上分号和等号,所以可以随便构造

Content-Disposition:u0;;;;!@#$%^&*(;asdasu0085d;085filename=11.aspx
Content-Disposition:filename=11.aspx
Content-Disposition:aaaaaaaaaaafilename=11.aspx;aaaaaaaaa

两个对比一下就知道

Content-Disposition: form-data; name="file";filename="11.aspx"
  1. form-data字段可以不要

  2. 可以随便在filenamename前随意填充字段

  3. 但是filenamename后必须跟随等号,并且末尾有分号标识结束。

在ExtractValueFromContentDispositionHeader函数中会对取的值进行Trim()处理,也能用u0085来处理

content-type同上

最后贴一张构造的图

从dotnet源码看⽂件上传绕waf

写在文后

Request.Files[0]的name字段是忽略大小写的,Request.Files[0]和Request.Files["file"]两种写法绕过时可能会出一些拿不到name的问题。

dotnet的特殊空白符如上文,但是位置一般只能放在两侧来用Trim去除。

来源:先知 

注:如有侵权请联系删除

从dotnet源码看⽂件上传绕waf

欢迎大家加群一起讨论学习和交流
(此群已满200人,需要添加群主邀请)

从dotnet源码看⽂件上传绕waf

从现在开始 不留余力地努力吧,

最差的结果 也不过是大器晚成。

原文始发于微信公众号(衡阳信安):从dotnet源码看⽂件上传绕waf

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月15日02:24:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   从dotnet源码看⽂件上传绕wafhttp://cn-sec.com/archives/819083.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息