返回

文章详情

解密视状态消息

Hacker News2026年7月7日 18:32

我最近有人联系我,提出了一个有趣的问题。他们在Windows应用程序日志中发现了一个1316事件,包含了一个可能恶意的视状态。唯一的问题是,它是加密的。更糟糕的是,他们唯一能访问的是主机的磁盘映像。在提取受影响网站的web.config文件后,他们发现被攻击网站配置了自动生成的密钥。他们能够从Windows注册表中转储自动生成的密钥,但不知道如何用这些密钥来解密他们的视状态。解密视状态的复杂性从传统设置的微不足道(只需从缓冲区末尾删除验证哈希,然后使用正确的密钥和对称算法解密)到现代设置的复杂,这通常涉及到使用反射“欺骗”IIS为我们解密值。我通常依赖CyberChef来解密传统视状态,并使用Blacklist3r来处理现代视状态。就个人而言,我发现这两种工具在解密视状态时都有点痛苦,所以我会在本文末尾分享一个新工具。回到我们最初的问题,无论我们的加密视状态是传统的还是现代的,拥有自动生成的密钥对我们帮助不大;如果我们想解密,仍然需要最终的机器密钥。但如何将存储在注册表或LSA秘密中的自动生成密钥Blob转换为我们实际可以使用的解密密钥呢?本文将是《视状态:永远无法修补的IIS被积极利用的日子》的续篇,我强烈建议在继续阅读本文之前先阅读那篇文章。在我上一篇文章中,我以高层次的概述了密钥生成过程,并提到了可以传递给密钥生成过程的一些修饰符,以确保各应用程序之间的密钥唯一性;然而,那篇文章主要关注于传统(但仍然占主导地位)加密配置,几乎没有提及应用程序应该朝着的现代配置。在本文中,我将讨论以下内容:如何生成自动生成的密钥如何从自动生成的密钥派生主机器密钥如何从主机器密钥派生最终机器密钥如何使用最终密钥解密视状态消息这次,我将讨论所有这些内容,包括传统和现代加密配置。什么是自动生成的密钥,它是如何生成的?“自动生成的密钥”这个名称似乎不太恰当,因为它们实际上并不是密钥,但这是微软在其代码和注册表中的称呼,因此我们在这里将沿用这一称呼。自动生成的密钥是一个1024字节的数据块,包含特定偏移位置的主IIS验证和解密机器密钥。这是存储在注册表或(加密的)LSA秘密中的值,并在运行时读取。我们可以看到这个“密钥”是如何在System.Web.HttpRuntime::SetAutogenKeys()中生成的:在本文中提到的每个命名空间.类.函数组合都可以在.NET框架的System.Web程序集找到。internal static byte [] s_autogenKeys = new byte [1024]; private static void SetAutogenKeys () { byte [] array = new byte [HttpRuntime . s_autogenKeys . Length]; byte [] array2 = new byte [HttpRuntime . s_autogenKeys . Length]; bool flag = false ; RNGCryptoServiceProvider rngcryptoServiceProvider = new RNGCryptoServiceProvider (); rngcryptoServiceProvider . GetBytes (array); if (! flag) { flag = UnsafeNativeMethods . EcbCallISAPI (IntPtr . Zero , UnsafeNativeMethods . CallISAPIFunc . GetAutogenKeys , array , array . Length , array2 , array2 . Length) == 1 ; } if (flag) { Buffer . BlockCopy (array2 , 0 , HttpRuntime . s_autogenKeys , 0 , HttpRuntime . s_autogenKeys . Length); return ; } Buffer . BlockCopy (array , 0 , HttpRuntime . s_autogenKeys , 0 , HttpRuntime . s_autogenKeys . Length); } 变量名通过dbSpy生成的不太好,因此在深入之前我们来清理一下:internal static byte [] s_autogenKeys = new byte [1024]; private static void SetAutogenKeys () { byte [] randBytes = new byte [HttpRuntime . s_autogenKeys . Length]; byte [] autogenKey = new byte [HttpRuntime . s_autogenKeys . Length]; bool existingKeyLoaded = false; RNGCryptoServiceProvider rngcryptoServiceProvider = new RNGCryptoServiceProvider (); rngcryptoServiceProvider . GetBytes (randBytes); if (! existingKeyLoaded) { existingKeyLoaded = UnsafeNativeMethods . EcbCallISAPI (IntPtr . Zero , UnsafeNativeMethods . CallISAPIFunc . GetAutogenKeys , randBytes , randBytes . Length , autogenKey , autogenKey . Length) == 1; } if (existingKeyLoaded) { Buffer . BlockCopy (autogenKey , 0 , HttpRuntime . s_autogenKeys , 0 , HttpRuntime . s_autogenKeys . Length); return ; } Buffer . BlockCopy (randBytes , 0 , HttpRuntime . s_autogenKeys , 0 , HttpRuntime . s_autogenKeys . Length); } 更好得多。当调用SetAutogenKeys时(这作为HttpRuntime初始化的一部分发生)

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡