窃取机器密钥以获取乐趣与收益(或乘 SharePoint 浪潮)
发布:2025-08-05 | 最后更新:2025-08-05 08:37:39 UTC
作者:Bojan Zdrnja(版本:1)
大约 10 天前,Microsoft SharePoint(CVE-2025-53770、CVE-2025-53771)的漏洞利用开始被公开滥用——我们在此处和此处写过相关文章。
原始的 SharePoint 漏洞是一个反序列化漏洞,允许攻击者执行任意命令——虽然这些命令可以是任何内容,但我们分析的大多数漏洞利用导致攻击者投放一个 ASPX 文件,该文件仅向他们显示 IIS 机器密钥。这促使我深入研究如何滥用此漏洞。
什么是 IIS 机器密钥?
IIS 和 ASP.NET 中的机器密钥是一个配置设置,用于确保服务器与客户端之间交换数据的安全性和完整性。
基本上,它负责验证和加密敏感数据,如 VIEWSTATE、cookie 和会话状态,保护它们免受篡改或未经授权的访问。IIS 管理员可以定义特定的机器密钥设置——配置方式有很多种,但本文我们将重点讨论 VIEWSTATE 保护。
VIEWSTATE 是 ASP.NET Web Forms 中使用的一种机制,用于在回发之间(即用户操作将页面发送回服务器时)持久化控件和页面数据的状态。它允许开发人员在表单提交后轻松存储各种控件的值。VIEWSTATE 始终由 IIS ASP.NET 应用程序使用。
由于 VIEWSTATE 可能包含敏感信息,因此应适当保护。这就是机器密钥发挥作用的地方——IIS 使用它们来防止 VIEWSTATE 被篡改,并(可选)加密其内容。
默认情况下,IIS(即使是 Windows Server 2025 上的最新版本)会启用 VIEWSTATE MAC(消息认证码)验证,但会将加密设置为“自动”,这意味着不使用加密,如下图所示:
除非开发人员决定在 VIEWSTATE 中存储机密内容,否则这不是一个大问题。
正如您现在可能猜到的那样,机器密钥用于执行验证——默认情况下使用 SHA1。还支持其他几种算法,其中 HMACSHA256 是第二常用的算法。
机器密钥处理
由于机器密钥用于验证 VIEWSTATE 的完整性,因此它显然是一个非常重要的安全元素。如果攻击者获取服务器的机器密钥,他们可以修改 VIEWSTATE(和 cookie)为任意值,并计算正确的 MAC,这可能允许他们进行各种滥用——甚至实现远程代码执行,如下文所示。
那么,如何处理这个问题呢?整个设置可能有点复杂,具体取决于 IIS 运行在哪个账户下,但在最常见的设置中,使用以下两种方法之一:
- 机器密钥由 IIS 自动生成。这是默认设置(您可以在上图中看到),在这种情况下,机器密钥存储在注册表中。
- 机器密钥由管理员生成并存储在 web.config 文件中。如果您在负载均衡器后面有一组需要共享会话的服务器,则这实际上是强制性的,因此这种设置非常常见!
窃取机器密钥
攻击者的最终目标是窃取目标 IIS 服务器使用的机器密钥。那么,他们如何实现这一点?
如果机器密钥存储在 web.config 文件中,在大多数情况下,它将以明文形式存储在那里!虽然可以加密配置部分,但这很少做。换句话说,能够获取 web.config 文件的攻击者基本上可以控制整个服务器!
例如,这可以通过 LFI(本地文件包含)或 XXE(XML 外部实体)漏洞来实现,这些漏洞允许攻击者获取文件内容。
如果机器密钥是自动生成的,则它存储在注册表中,这意味着攻击者需要在服务器上执行代码才能获取此密钥,但这里需要强调一件重要的事情:如果攻击者获得代码执行权限(即使通过 ASPX 文件),也无法阻止他们读取机器密钥!
回到我们的 SharePoint 故事——一旦原始攻击者利用易受攻击的 SharePoint 服务器,他们上传了以下 ASPX 文件:
|
|
这个脚本做什么?它会尝试读取 web.config 文件,并显示验证和加密密钥以及使用的模式。如果机器密钥存储在 web.config 中,它将被泄露给攻击者,如下图所示:
有了机器密钥,攻击者现在可以在受影响的服务器上实现 RCE,这是由于 VIEWSTATE 反序列化的方式(这是一个功能!)——更多内容见下文,但让我们看看另一种情况,当机器密钥是自动生成且未存储在 web.config 中时:
哦!攻击者运气不好,这个脚本无法获取机器密钥。呼,一切都好,我们不需要做任何事情……或者我们需要吗?记得我上面写过,自动生成的机器密钥存储在注册表中。有什么能阻止攻击者投放一个更好的可以读取注册表的 ASPX 文件吗?
不幸的是,没有,正如 Soroush Dalili 在他们精彩的博客中所写——无论密钥存储在哪里,都可以简单地读取它。Soroush 发布了一个小的 ASPX 文件,可以遍历机器密钥的所有潜在位置。
显然,SharePoint 攻击者要么不关心其他位置(并且对 web.config 中的密钥感到满意),要么不知道这一点,但如果您使用 Soroush 的脚本,即使机器密钥是自动生成的,您也可以获取它,如下所示,我使用相同的应用程序作为概念验证:
这里的底线是:如果任何人在 IIS 服务器上获得任何代码执行权限,您绝对需要重新生成服务器的机器密钥。Windows 不会自动为您执行此操作,并且此密钥在重启后仍然存在!
远程代码执行
那么,现在可以用机器密钥做什么?
虽然我们可以修改 VIEWSTATE 中的值(读取它有点困难,因为它是序列化的,但当然不是不可能),但也可以使用 Alvaro Munoz 出色的 ysoserial.net,它内置支持生成 VIEWSTATE 对象。
现在我们有了有效的机器密钥,ysoserial.net 允许我们创建一个对象,该对象在服务器端反序列化时将执行代码。由于 MAC 将是有效的(甚至如果需要的话是加密的),IIS 将愉快地尝试使用 LosFormatter 类反序列化它,这将最终允许通过反序列化实现远程代码执行,因为这里可以使用已知的 gadget。
这里有两个关键点:
- 如果攻击者拥有有效的机器密钥,管理员无法阻止此操作。
- 恶意 VIEWSTATE 参数可用于服务器上的任何 ASPX 脚本,不需要是最初易受攻击的脚本。关于如何基于应用程序路径生成有效的 VIEWSTATE 参数有一些注意事项,但有许多其他资源解释了如何执行此操作。
重申一下——一旦攻击者拥有有效的机器密钥,他们基本上就拥有了一个后门,可以随时使用,只要机器密钥没有被更改!
PoC || GTFO
让我们演示一下。我有一个非常简单的应用程序,允许用户输入他们的名字(并将在未来的日记中使用),如下所示:
当单击提交按钮时,发送以下请求:
现在,我设置的 IIS 服务器使用自动生成的机器密钥,使利用更有趣(注意我没有说更困难)。使用 Soroush 发布的脚本时,可以再次看到以下信息:
这为我们提供了利用此服务器所需的所有信息。
我们将使用 ysoserial.net 来执行此操作,具体使用以下选项:
- 我们将使用的插件是 ViewState,它允许我们生成恶意的 VIEWSTATE 对象,前提是我们知道机器密钥。
- gadget 链将是 TextFormattingRunProperties——它通常生成最短的有效负载并支持 LosFormatter。
- 命令将是我们的 PowerShell,它将连接到我们的 Netcat 监听器。
- 最后,我们需要提供以下内容:
- 验证密钥是上面的机器密钥。我将使用应用程序特定的验证密钥,因为我们可以看到,除了机器密钥是自动生成的之外,服务器正在使用 IsolateApps,因此每个应用程序都有自己的机器密钥,该密钥源自初始密钥。
- 验证算法将是 HMACSHA256。
- 我的路径和应用程序路径将对应于我正在攻击的应用程序(有关此的更多信息,请参阅 Soroush 的帖子)。
- 最后,我使用适用于 .NET 4.0 的算法。
我们现在需要做的就是返回并重新发送请求,但这次使用我们的恶意 VIEWSTATE 对象:
响应将是 500 内部服务器错误,但这就是我们想要的:
我们得到了我们的反向 shell 快乐舞蹈:
最后,攻击者现在可以在属于此应用程序的任何页面上使用此恶意 VIEWSTATE 对象,无论发送什么其他参数,因为 IIS 将首先尝试反序列化接收到的 VIEWSTATE 对象。这就是他们的持久后门。
检测
IIS 至少会在 Viewstate 验证失败时记录一个事件。这里的失败并不意味着 MAC 不正确(这被静默忽略),而是当验证过程失败时,这将在反序列化被利用时发生。
完整的 VIEWSTATE 对象被记录,因此也允许检查发生了什么。如果您还没有这样做,请确保您正在监视 Windows 应用程序代码中的事件代码 4009。这样的事件将如下所示:
–
Bojan
?X | LinkedIn
INFIGO IS | An Allurity Group 成员
关键词:machine key iis ysoserialnet