AD-FS 安全 | FoggyWeb:有针对性的 NOBELIUM 恶意软件导致持久性后门
2022-8-25 19:35:26 Author: mp.weixin.qq.com(查看原文) 阅读量:5 收藏

前言

Microsoft 继续与合作伙伴和客户合作,以跟踪和扩展我们对我们称为 NOBELIUM 的威胁行为者的了解,该行为者是SUNBURST 后门、TEARDROP 恶意软件和相关组件的幕后黑手。正如我们之前所说,我们怀疑 NOBELIUM 可以利用其活动中经常展示的重要运营资源,包括定制的恶意软件和工具。2021 年 3 月,我们分析了 NOBELIUM 的GoldMax、GoldFinder 和 Sibot 恶意软件,它用于分层持久性。然后,我们在 5 月发布了另一篇文章,当时我们分析了演员的早期工具集,包括EnvyScout、BoomBox、NativeZone 和 VaporRage。

此博客是对新检测到的 NOBELIUM 恶意软件的另一项深入分析:Microsoft 威胁情报中心 (MSTIC) 将其称为FoggyWeb的一个后利用后门。如之前的博客所述,NOBELIUM 采用多种策略来进行凭据盗窃,目的是获得对 Active Directory 联合服务 ( AD FS ) 服务器的管理员级别访问权限。一旦 NOBELIUM 获得凭据并成功入侵服务器,攻击者就会依赖该访问权限来维持持久性并使用复杂的恶意软件和工具加深其渗透。NOBELIUM 使用 FoggyWeb 远程窃取受感染 AD FS 服务器的配置数据库、解密的令牌签名证书和令牌解密证书,以及下载和执行其他组件。早在 2021 年 4 月,就已经在野外观察到 FoggyWeb 的使用。

Microsoft 已通知所有被观察到成为此活动目标或受到威胁的客户。如果您认为您的组织已被入侵,我们建议您

  • 审核您的本地和云基础架构,包括配置、每个用户和每个应用程序的设置、转发规则以及参与者可能为维护其访问权限而进行的其他更改
  • 删除用户和应用程序访问权限,检查每个配置,并按照记录的行业最佳实践重新颁发新的、强大的凭据。
  • 使用保护 AD FS 服务器 中所述的硬件安全模块 (HSM)以防止 FoggyWeb 泄露机密。

Microsoft 安全产品已针对此恶意软件实施检测和保护。Azure Sentinel的危害指标 (IOC)、缓解指南、检测详细信息和搜寻查询微软 365在此分析结束时和产品门户中提供了 Defender 客户。Active Directory 联合身份验证服务 ( AD FS ) 服务器在本地运行,客户还可以遵循有关保护 AD FS 服务器免受攻击的详细指南。

FoggyWeb:针对 AD FS 的后门

FoggyWeb 是一种被动且具有高度针对性的后门,能够从受感染的 AD FS 服务器远程窃取敏感信息。它还可以从命令和控制 (C2) 服务器接收其他恶意组件,并在受感染的服务器上执行它们。

在破坏 AD FS 服务器后,观察到 NOBELIUM 在系统上删除了以下两个文件(需要管理员权限才能将这些文件写入下面列出的文件夹):

  • %WinDir%\ADFS\version.dll
  • %WinDir%\SystemResources\Windows.Data.TimeZones\pris\Windows.Data.TimeZones.zh-PH.pri

FoggyWeb 存储在加密文件Windows.Data.TimeZones.zh-PH.pri中,而恶意文件version.dll可以说是它的加载器。AD FS 服务可执行文件Microsoft.IdentityServer.ServiceHost.exe通过涉及核心公共语言运行时 (CLR) DLL 文件的DLL 搜索顺序劫持技术加载所述 DLL文件(在 FoggyWeb 加载程序部分中有详细描述)。该加载程序负责加载加密的 FoggyWeb 后门文件,并利用自定义的轻量级加密算法 (LEA) 例程来解密内存中的后门。

在对后门进行去混淆后,加载程序继续在 AD FS 应用程序的执行上下文中加载 FoggyWeb。加载程序是一个非托管应用程序,它利用 CLR 托管接口和 API 将后门程序(一个托管 DLL)加载到执行合法 AD FS 托管代码的同一应用程序域中。这将授予对 AD FS 代码库和资源的后门访问权限,包括 AD FS 配置数据库(因为它继承了访问配置数据库所需的 AD FS 服务帐户权限)。

加载 version.dll 后 Microsoft.IdentityServer.ServiceHost.exe 的结构示意图

加载后,FoggyWeb 后门(最初由其开发人员命名为Microsoft.IdentityServer.WebExtension.dll)充当被动且持久的后门,允许滥用安全断言标记语言 (SAML) 令牌。后门为参与者定义的 URI 配置 HTTP 侦听器,这些 URI 模仿目标的 AD FS 部署使用的合法 URI 的结构。自定义侦听器被动监视从 Intranet/Internet 发送到 AD FS 服务器的所有传入 HTTP GET 和 POST 请求,并拦截与参与者定义的自定义 URI 模式匹配的 HTTP 请求。此版本的 FoggyWeb 为以下硬编码 URI 模式(可能因目标而异)配置侦听器:

  • HTTP GET URI 模式:
    • /adfs/portal/images/theme/light01/profile.webp
    • /adfs/portal/images/theme/light01/background.webp
    • /adfs/portal/images/theme/light01/logo.webp
  • HTTP POST URI 模式:
    • /adfs/services/trust/2005/samlmixed/上传

上面的每个 HTTP GET/POST URI 模式都对应一个 C2 命令:

  • 当 AD FS 服务器收到包含 URI 模式*/adfs/portal/images/theme/light01/profile.webp的 HTTP GET 请求时,后门会检索受感染 AD FS 服务器的**令牌签名证书***,然后将证书混淆并返回给请求的发出者。
  • 同样,当 AD FS 服务器收到包含 URI 模式*/adfs/portal/images/theme/light01/background.webp的 HTTP GET 请求时,后门会检索受感染 AD FS 服务器的**令牌解密证书***,然后进行混淆并返回向请求的颁发者颁发证书。
  • 当 AD FS 服务器收到包含 URI 模式*/adfs/portal/images/theme/light01/logo.webp*的 HTTP GET 请求时,后门会检索受感染服务器的 AD FS 配置数据,对数据进行混淆,并返回混淆后的数据。向请求的发出者提供数据。
  • 当 AD FS 服务器收到包含 URI 模式*/adfs/services/trust/2005/samlmixed/upload*的 HTTP POST 请求时,后门会将经过混淆和压缩的 POST 数据视为 .NET 程序集或源代码。如果是程序集,则后门在 AD FS 进程的执行上下文中执行程序集。如果是源代码,则后门会动态编译源代码并继续在 AD FS 进程的执行上下文中执行生成的内存驻留程序集。

下图说明了攻击者用来与位于受感染的面向 Internet 的 AD FS 服务器上的 FoggyWeb 后门通信的方法。

FoggyWeb 攻击链示意图

由于 FoggyWeb 在主 AD FS 进程的上下文中运行,因此它继承了访问 AD FS 配置数据库所需的 AD FS 服务帐户权限。这与必须在 AD FS 服务帐户的用户上下文下执行的工具(如ADFSDump)形成对比。此外,由于 FoggyWeb 与 AD FS 托管代码加载到相同的应用程序域中,因此它可以通过编程方式访问合法的 AD FS 类、方法、属性、字段、对象和组件,随后 FoggyWeb 会利用这些来促进其恶意操作. 例如,这允许 FoggyWeb 无需连接到 WID 命名管道或手动运行 SQL 查询来检索配置信息(例如,获取来自配置数据的EncryptedPfx blob)。FoggyWeb 也与 AD FS 版本无关;它不需要跟踪旧版与现代配置表名称和架构、命名管道名称以及 AD FS 的其他版本相关属性。

FoggyWeb 加载程序

文件version.dll是一个恶意加载器,负责从文件系统中加载一个加密的后门文件,解密后门文件,并将其加载到内存中。此恶意 DLL 与位于*%WinDir%\System32*文件夹中的合法 Windows DLL 共享名称,旨在放置在 AD FS 主文件夹*%WinDir%\ADFS*中,AD FS 服务可执行Microsoft。IdentityServer.ServiceHost.exe位于(出于本节后面所述的原因)。

启动 AD FS 服务 ( adfssrv ) 后,将执行服务可执行文件Microsoft.IdentityServer.ServiceHost.exe。作为基于 .NET 的托管应用程序,Microsoft.IdentityServer.ServiceHost.exe导入名为mscoree.dll的非托管 Windows DLL 。

显示 Microsoft.IdentityServer.ServiceHost.exe 正在导入 mscoree.dll 的屏幕截图。

文件mscoree.dll动态加载另一个名为**mscoreei.dll的非托管 Windows/CLR DLL 。如下图,mscoreei.dll有一个名为**version.dll的延迟加载导入(Delay Import)。

显示 mscoreei.dll 的屏幕截图有一个名为 version.dll 的延迟加载导入(Delay Import)

观察到具有现有管理权限的 NOBELIUM在 AD FS 服务可执行文件Microsoft.IdentityServer.ServiceHost.exe所在的*%WinDir%\ADFS\文件夹中放置了一个名为version.dll的恶意加载程序。重新启动系统或 AD FS 服务后,Microsoft.IdentityServer.ServiceHost.exe会加载mscoree.dll,而后者又会加载mscoreei.dll。如上所述,mscoreei.dll有一个名为version.dll的延迟加载导入。一旦加载,而不是从%WinDir%\System32*文件夹*mscoreei.dll加载合法的version.dll加载攻击者在%WinDir%\ADFS*文件夹中植入的恶意version.dll(简称DLL搜索顺序劫持),如下调用栈所示。

显示文件夹 mscoreei.dll 的调用堆栈屏幕截图加载了攻击者在 %WinDir%\ADFS\ 文件夹中植入的恶意 version.dll

恶意加载程序version.dll充当所有合法**version.dll导出函数调用的代理。如下所示,它导出了与version.dll的合法版本相同的 17 个函数名。

恶意version.dll的导出函数都是短存根,它们调用标记为TrampolineFunction的单个 trampoline 函数,如下面的屏幕截图所示。

恶意version.dll的导出功能截图

下面是蹦床功能的伪代码。

蹦床功能伪代码截图

此蹦床功能负责以下工作:

  • 调用一个函数(被分析师标记为*LoadDecryptExecuteBackdoor()*)从文件系统中加载一个后门文件,然后在内存中解密并执行该文件
  • 从version.dll的合法版本将执行转移到最初调用的目标函数。

trampoline 函数通过保存某些 CPU 寄存器的值,从version.dll的合法版本中保留用于该函数的参数/寄存器的值。它首先将它们压入堆栈,然后调用上面的LoadDecryptExecuteBackdoor()函数,然后在将执行从version.dll的合法版本转移到函数之前恢复它们。

显示 trampoline 函数的代码屏幕截图通过保存某些 CPU 寄存器的值,从 version.dll 的合法版本中保留了用于该函数的参数/寄存器的值

调用时,*LoadDecryptExecuteBackdoor()会尝试创建一个名为{2783c149-77a7-5e51-0d83-ac0566daff96}*的 Windows 事件,以确保只有一个加载程序副本在系统上主动运行。然后在一个新线程中检查是否存在以下文件(硬编码路径字符串):

C:\Windows\SystemResources\Windows.Data.TimeZones\pris\Windows.Data.TimeZones.zh-PH.pri

Windows.Data.TimeZones.zh-PH.pri是一个加密的后门文件,放置在上面的文件夹中。MSTIC 将这个后门文件称为 FoggyWeb,我们的分析在下一节。

Microsoft.IdentityServer.ServiceHost.exe本身是一个非托管 Windows 可执行文件,在编译高级 AD FS 托管代码时生成。执行时, Microsoft.IdentityServer.ServiceHost.exe中的非托管代码利用公共语言运行时 (CLR) 在虚拟运行时环境中运行托管 AD FS 代码。此虚拟运行时环境由一个或多个应用程序域组成,它们为运行时环境提供了一个隔离单元,并允许不同的应用程序在进程内的不同容器中运行。托管 AD FS 代码在虚拟运行时环境内的应用程序域内执行。

FoggyWeb 后门(也是托管 DLL)旨在与合法的 AD FS 代码一起运行(即,在同一应用程序域中)。这意味着 FoggyWeb 加载程序要在 AD FS 代码旁边加载后门,它需要获得对 AD FS 代码在其中执行的同一应用程序域的访问权限。由于 FoggyWeb 加载程序version.dll是非托管应用程序,因此它无法直接访问托管 AD FS 代码在其中执行的虚拟运行时环境。加载程序克服了这一限制,并通过利用 CLR 托管接口和 API 访问执行 AD FS 代码的虚拟运行时环境,将后门与 AD FS 代码一起加载。

加载程序执行以下高级操作:

  • 枚举 AD FS 进程Microsoft.IdentityServer.ServiceHost.exe中加载的所有 CLR
  • 对于每个 CLR,枚举所有正在运行的应用程序域并为每个域执行以下操作:
    • 将以下加密的FoggyWeb后门文件的内容读入内存:C:\Windows\SystemResources\Windows.Data.TimeZones\pris\Windows.Data.TimeZones.zh-PH.pri
    • 使用轻量级加密算法 (LEA) 对加密的 FoggyWeb 后门文件进行解密。LEA-128 密钥调度使用以下硬编码主密钥来生成轮密钥:
用于生成轮密钥的硬编码主密钥的屏幕截图

解密每个 16 字节密码块后,加载程序使用以下 XOR 密钥对每个单独的解密/明文块进行解码:

用于解码每个单独的解密/明文块的 XOR 密钥的屏幕截图

这相当于首先 LEA 解密整个文件,然后对解密的数据进行 XOR 解码(而不是对每个单独的 16 字节块进行解密和 XOR 解码)。

    • 创建一个安全数组并将解密后的 FoggyWeb 后门字节复制到数组中。然后它调用当前应用程序域的Load()函数将 FoggyWeb DLL 加载到应用程序域中。在将 FoggyWeb DLL 加载到当前应用程序域之后,加载器从 DLL 调用以下方法:Microsoft.IdentityServer.WebExtension.WebHost

在执行周期的这一点上,FoggyWeb DLL 被加载到一个或多个运行合法 AD FS 代码的应用程序域中。这意味着后门代码与 AD FS 代码一起运行,具有与 AD FS 应用程序相同的访问和权限。由于后门与 AD FS 代码加载在同一应用程序域中,因此它可以通过编程方式访问各种 AD FS 模块用来执行其合法功能的合法类、方法、属性、字段、对象和组件。这种访问允许 FoggyWeb 后门直接与 AD FS 代码库(即,不是外部磁盘驻留工具)交互,并有选择地调用促进其恶意操作所需的本机 AD FS 方法。

雾网后门

该恶意驻留内存 DLL(最初由其开发人员命名为Microsoft.IdentityServer.WebExtension.dll )用作针对 AD FS 的后门。它由主 AD FS 服务进程Microsoft.IdentityServer.ServiceHost.exe通过恶意加载程序组件加载。

加载后,后门会启动一个 HTTP 侦听器,该侦听器侦听包含以下 URI 模式的 HTTP GET 和 POST 请求:

  • HTTP GET URI 模式:*/adfs/portal/images/theme/light01/*
  • HTTP POST URI 模式:*/adfs/services/trust/2005/samlmixed/upload*

如下所示,URI 模式在后门中进行了硬编码,并模仿了目标 AD FS 部署使用的合法 URI 的结构。

模仿目标 AD FS 部署使用的合法 URI 结构的后门结构屏幕截图。

一旦后门接收到包含上述 URI 模式之一的 HTTP 请求,侦听器就会继续使用 HTTP GET 或 HTTP POST 回调/处理程序方法(分别为ProcessGetRequest()ProcessGetRequest() )处理该请求。

显示使用 HTTP GET 或 HTTP POST 回调/处理程序方法处理请求的侦听器的代码屏幕截图

HTTP GET 处理程序

包含 URI 模式*/adfs/portal/images/theme/light01/的传入 HTTP GET 请求由后门的ProcessGetRequest()*方法处理。

ProcessGetRequest() 方法的屏幕截图

如果对文件扩展名为.webp的文件/资源发出传入的 HTTP GET 请求,则*ProcessGetRequest()*方法继续处理该请求。否则,该请求将被后门忽略。此外,如果请求的文件名与以下三个硬编码名称之一匹配,则后门将请求视为攻击者发出的 C2 命令。

显示硬编码名称的代码屏幕截图

以下 URL 模式被视为 C2 命令:

  • /adfs/portal/images/theme/light01/profile.webp
  • /adfs/portal/images/theme/light01/background.webp
  • /adfs/portal/images/theme/light01/logo.webp

前两个 C2 命令profile.webpbackground.webp(上面屏幕截图中的*UrlGetFileNames[0]UrlGetFileNames[1])是通过调用后门的Service.GetCertificate()*方法来处理的。

Service.GetCertificate() 方法的代码截图

顾名思义,此方法负责从 AD FS 服务配置数据库检索 AD FS 证书(令牌签名或令牌加密证书,取决于传递给该方法的certificateType参数的值)。

***分析师注释:*请参阅附录以深入分析Service.GetCertificate() 方法以及它如何获取和解密令牌签名或加密证书。

如上图所示,当 C2 命令profile.webp ( UrlGetFileNames[0] ) 被发送到后门时(通过对 URI /adfs/portal/images/theme/light01/profile.webp发出 HTTP GET 请求) ,后门检索受感染 AD FS 服务器的令牌签名证书***。类似地,当 C2 命令background.webp ( UrlGetFileNames[1] ) 被发送到后门时(通过对 URI /adfs/portal/images/theme/light01/background.webp发出 HTTP GET 请求),后门检索受感染的 AD FS 服务器的**令牌加密证书***。

第三个 C2 命令logo.webp ( UrlGetFileNames[2] ) 通过向以下 URI 发送 HTTP GET 请求来触发:*/adfs/portal/images/theme/light01/logo.webp。C2 命令通过调用后门的GetInfo()*方法来处理。

后门GetInfo()方法的代码截图

*GetInfo()*方法负责转储受感染服务器的 AD FS 服务配置数据。

转储 AD FS 服务配置数据的 GetInfo() 方法的屏幕截图

如上所示,AD FS 服务配置数据是通过ServiceSettingsData属性获取的,该属性从 AD FS 服务配置数据库 Windows 内部数据库 (WID) 中检索数据。

在将 C2 命令的输出(即令牌签名证书、令牌加密证书或 AD FS 服务配置数据)在 HTTP 200 响应中返回给 C2 之前,后门首先通过调用其方法来混淆输出命名为*GetWebpImage()*。

GetWebpImage() 方法的代码截图

GetWebpImage *()*方法负责将 C2 命令的输出伪装成合法的 WebP 文件(通过添加适当的 RIFF/WebP 文件头魔术/字段)并对生成的 WebP 文件进行编码。

伪装 C2 输出的 GetWebpImage() 方法的代码截图

*GetWebpImage()*使用以下辅助方法来创建和编码包含 C2 命令输出的虚假 WebP 文件:

  • *GetWebpImage()首先调用Webp.GetFrame()*方法,该方法负责压缩 C2 命令的输出并将压缩后的版本复制到一个新数组(0 填充为 32 字节的倍数)。压缩数据的长度作为新数组的前四个字节添加。
GetWebpImage() 首先调用 Webp.GetFrame() 方法的代码截图

为了压缩数据,*GetFrame()调用Common.Compress()*方法,该方法用于通过利用 C# GZipStream 压缩类来压缩数据。

GetFrame() 的代码屏幕截图调用 Common.Compress() 方法

出于演示目的,假设 C2 命令产生以下数据(一个 256 字节的伪随机生成的字节数组)。

给定上述数据(即示例 C2 命令输出),*GetFrame()*返回以下字节数组。

GetFrame() 返回字节数组的截图
  • 接下来,*GetWebpImage()调用Webp.GetWebpHeader()方法,传入上一步中**GetFrame()返回的字节数组的大小。GetWebpHeader()*负责创建和返回包含自定义 RIFF WebP 文件魔术/标题字节的数组。
调用 Webp.GetWebpHeader() 方法的 GetWebpImage() 代码的屏幕截图

上面的数组变量包含以下 32 字节硬编码 RIFF/WebP 标头字节。

32 字节硬编码 RIFF/WebP 标头字节的屏幕截图

如果传递给*GetWebpHeader()的数组大小(由GetFrame()*返回)超过 8,192 字节,则标头字节的索引 26 和 28 处的字节(最初设置为 0x00)将替换为 0x80。否则,索引 26 和 28 处的字节将替换为 0x40,如下所示。

显示索引 26 和 28 处的字节被替换为 0x40 的屏幕截图

*GetWebpHeader()然后将上面的自定义 RIFF/WebP 标头返回给GetWebpImage()*。

  • 接下来,GetWebpImage()通过将 GetWebpHeader() 返回的自定义 RIFF/WebP 标头字节附加到GetFrame()**返回的数组(包含 C2 命令输出的压缩版本的数组)来创建一个新数组。

GetWebpImage()调用后门的Common.ProtectData()方法对新数组中包含压缩字节的部分进行编码(即,它不编码自定义 RIFF/WebP 标头)。作为第二个参数,GetWebpImage()将第一个压缩字节的偏移量传递给ProtectData()(如上表所示,在这种情况下,0x20 或 32 是第一个压缩字节的偏移量)。ProtectData()使用动态XOR 密钥和自定义 XOR 方法对压缩数据进行 XOR 编码。

最初,12 字节硬编码 XOR 密钥数组包含以下(种子)字节。

种子字节的屏幕截图

如上面的屏幕截图所示,压缩数据的每个字节都与 XOR 密钥数组中的一个字节进行异或。压缩数据的第一个字节 (0x17) 与位于密钥数组 (0x77) 偏移量 8 处的 XOR 密钥字节进行异或运算。

显示压缩数据第一个字节的屏幕截图

在将压缩数据的第一个字节与位于密钥数组偏移量 8 处的 XOR 密钥字节进行异或运算后,XOR 密钥字节本身会被新值覆盖。

用新值覆盖的 XOR 键字节的屏幕截图

例如,位于 XOR 密钥数组 (0x77) 偏移 8 处的 XOR 密钥字节通过以下操作被 0xEE 覆盖。

位于 XOR 密钥数组 (0x77) 的偏移量 8 处的 XOR 密钥字节的屏幕截图被 0xEE 覆盖

压缩数据的第二个字节 (0x01) 与位于密钥数组偏移量 9 处的 XOR 密钥字节 ( 33 % 12 = 9 ) 进行异或运算,依此类推,直到密钥滚动到 XOR 数组的第一个字节 (如上所述,XOR 密钥字节在每次编码操作后被覆盖)。下面是样本压缩数组的 XOR 编码版本。

压缩数据第二字节截图

在上述步骤之后,*GetWebpImage()*将以下示例数据返回给调用它的方法,以混淆和隐藏每个 C2 命令 ( ProcessGetRequest() ) 的输出。

img

如前所述,*ProcessGetRequest()*在 HTTP 200 响应中将上面生成的假 RIFF/WebP 文件(包含被盗的令牌签名证书、令牌加密证书或 AD FS 服务配置数据)返回给 C2。

ProcessGetRequest() 在 HTTP 200 响应中将伪造的 RIFF/WebP 文件返回到 C2 的代码屏幕截图

如果后门无法成功执行 C2 命令,则改为向 C2 返回 HTTP 404 响应。

HTTP POST 处理程序

与 URI 模式*/adfs/services/trust/2005/samlmixed/upload匹配的传入 HTTP POST 请求由ProcessPostRequest()*方法处理。

ProcessPostRequest() 方法的代码截图

此方法确保传入的 HTTP POST 请求的ContentType值以“xml”(不区分大小写)结尾,并且 HTTP POST 数据包含名为X509CertificateSignatureValue的两个 XML 元素(例如,以字符串“ < X509Certificate> ”并以字符串  ”结尾)。

确保传入 HTTP POST 请求的 ContentType 值以“xml”结尾的 ProcessPostRequest() 方法的屏幕截图

如果 XML 数据包含这两个元素,则后门会执行以下操作:

  • 解码SignatureValueX509Certificate元素的值,方法是首先使用 Base64 解码值,然后对每个解码值调用Common.UprotectData()方法。
解码 SignatureValue 和 X509Certificate 元素值的代码截图

UprotectData ()方法将 Base64 解码值的前两个字节视为两个字节的 XOR 密钥。它对其余数据(即第三个字节)调用Common.ProtectData()方法(在上一节中介绍),然后使用两字节 XOR 密钥对**Common.ProtectData( ) . 换句话说,*UprotectData()利用Common.ProtectData()*删除第一层 XOR 编码,然后另一个 XOR 例程删除应用于数据的第二层 XOR 编码。

UprotectData() 利用 Common.ProtectData() 删除第一层 XOR 编码和另一个 XOR 例程的代码截图
  • 调用Service.ExecuteAssembly()方法来处理解码后的SignatureValueX509Certificate值。如下图,解码后的X509Certificate值是调用*Common.Decompress()*方法解压/膨胀的第一个GZip。
解码 X509Certificate 值的屏幕截图,通过调用 Common.Decompress() 方法解压/膨胀的第一个 GZip

在一个新线程中,*Service.ExecuteAssembly()调用Service.ExecuteAssemblyRoutine()*方法来处理数据。

Service.ExecuteAssembly() 调用 Service.ExecuteAssemblyRoutine() 方法的屏幕截图
  • ExecuteAssemblyRoutine()检查解码后的X509Certificate值是否以“MZ”开头(或字节0x4D 0x5A,十进制数7790的十六进制表示,如下面的屏幕截图所示)。
显示以“MZ”或字节 0x4D 0x5A 开头的解码 X509Certificate 值的屏幕截图,十进制数 77 和 90 的十六进制表示
  • 如果解码后的X509Certificate值以“MZ”开头,则后门将解码后的数据视为基于 .NET 的程序集/有效负载,并继续调用其Service.ExecuteBinary()方法以在内存中加载和执行 DLL 有效负载。在内存中加载 DLL 后,ExecuteBinary()继续从加载的 DLL 调用特定方法。调用该方法所需的方法名称和参数在解码的SignatureValue数据中提供给后门。
Service.ExecuteBinary() 方法的代码截图,该方法在内存中加载并执行 DLL 有效负载

如果解码后的X509Certificate以 MZ 开头,则后门将解码后的X509Certificate值视为基于 C# 的有效载荷的源代码,并调用其*Service.ExecuteSource()*方法在内存中动态编译和执行有效载荷。

Service.ExecuteSource() 方法的代码截图,该方法在内存中动态编译和执行有效负载

在处理包含 XML 元素X509CertificateSignatureValue的 HTTP POST 请求后,后门使用 HTTP 204 响应代码响应请求。如果 HTTP POST 没有上述元素,后门会使用 HTTP 404 响应码响应请求。

附录:获取和解密 AD FS 令牌

顾名思义,Service.GetCertificate()方法负责从 AD FS 服务检索 AD FS 证书(令牌签名或令牌加密证书,取决于传递给该方法的certificateType参数的值)配置数据库。

Service.GetCertificate() 方法的代码截图,负责检索 AD FS 证书

该方法执行以下操作来检索所需的证书:

  • 调用另一个名为GetServiceSettingsDataProvider()的方法,从已加载的程序集Microsoft.IdentityServer创建类型为Microsoft.IdentityServer.PolicyModel.Configuration.ServiceSettingsDataProvider的实例。
调用 GetServiceSettingsDataProvider() 方法的代码截图
GetServiceSettingsDataProvider() 方法的代码截图
  • 调用上述*ServiceSettingsDataProvider实例的**GetServiceSettings()*成员/方法以获取 AD FS 服务配置设置。
调用 GetServiceSettings() 方法的代码截图
  • 获取 AD FS 服务设置的值(从SecurityTokenService属性),从服务设置中提取EncryptedPfx blob 的值,并使用 Base64 解码 blob。
用于提取 EncryptedPfx blob 值的代码屏幕截图
  • 调用另一个名为GetAssemblyByName()的方法以按名称枚举所有已加载的程序集并找到已加载的程序集Microsoft.IdentityServer.Service此方法从Microsoft.IdentityServer.Service.Configuration.AdministrationServiceState类型的对象(来自Microsoft.IdentityServer.Service程序集)中检索名为*_state_certificateProtector*的两个字段的值。
img
img

AdministrationServiceState类/对象包含执行和处理客户端请求所需的配置信息。*_state字段用于维护AdministrationServiceState类/对象的当前状态(来自Microsoft.IdentityServer.Service.dll*的屏幕截图)。

img

AdministrationServiceState对象(存储在*_state字段中)包含另一个名为_certificateProtector*的字段。

img

_certificateProtector字段存储用于分布式密钥管理 (DKM)的 Data Protector 类DkmDataProtector的实例。DkmDataProtector类实现了一个名为Unprotect()的方法,**该方法最终调用了DKM/IDKM的Unprotect()方法(来自**Microsoft.IdentityServer.dll的屏幕截图)。

img

DKM Unprotect()方法从 Microsoft.IdentityServer.Dkm.DKMBase 继承了一个名为Unprotect ()的方法(来自Microsoft.IdentityServer.Dkm.dll的屏幕截图)。

img

Microsoft.IdentityServer.Dkm.DKMBase中的Unprotect()方法(如上所示)提供了解密存储在EncryptedPfx blob 中的加密证书(PKCS12 对象)的功能。

了解可通过*_certificateProtector字段访问的**Unprotect()方法的可用性后,后门会调用Unprotect()方法来解密存储在所需证书类型的EncryptedPfx* blob 中的加密证书(AD FS 令牌签名或加密证书)。

img

本附录中描述的技术变体由 Douglas Bienstock 和 Austin Baker 在 2019 年的 TROOPERS 会议上公开展示(我是 AD FS,你也可以:攻击 Active Directory 联合服务)。但是,FoggyWeb 使用的方法与公开提供的方法不同,因为 FoggyWeb 利用AdministrationServiceState类/对象中的**_state和*_certificateProtector字段来促进对 Data Protector 类DkmDataProtector的访问(用于访问和调用Unprotect()*方法)。

妥协指标 (IOC)

类型威胁名称威胁类型指标
MD5雾网装载机5d5a1b4fafaf0451151d552d8eeb73ec
SHA-1雾网装载机c896ece073dd01191cbc1d462bc2f47161828a83
SHA-256雾网装载机231b5517b583de102cde59630c3bf938155d17037162f663874e4662af2481b1
MD5雾网后门(加密)9ff9401315d0f7258a9fcde0cfdef02b
SHA-1雾网后门(加密)4597431f26424cb814c917168fa8d74d01ab7cd1
SHA-256雾网后门(加密)da0be762bb785085d36aec80ef1697e25fb15414514768b3bcaf798dd9c9b169
MD5雾网后门(已解密)e9671d294ce41fe6dbb9637dc0157a88
SHA-1雾网后门(已解密)85cfeccbb48fd9f498d24711c66e458e0a80cc90
SHA-256雾网后门(已解密)568392bd815de9b677788addfc4fa4b0a5847464b9208d2093a8623bbecd81e6

缓解措施

客户应检查其 AD FS 服务器配置并实施更改以保护这些系统免受攻击:

  • 保护 AD FS 和 Web 应用程序代理的最佳实践

我们强烈建议组织通过以下最佳实践强化和保护 AD FS 部署:

  • 确保只有 Active Directory 管理员和 AD FS 管理员拥有 AD FS 系统的管理员权限。
  • 减少所有 AD FS 服务器上的本地管理员组成员身份。
  • 要求所有云管理员使用多重身份验证 (MFA)。
  • 通过代理确保最小的管理能力。
  • 通过主机防火墙限制网络访问。
  • 确保 AD FS 管理员使用管理员工作站来保护他们的凭据。
  • 将 AD FS 服务器计算机对象放在不托管其他服务器的顶级 OU 中。
  • 确保适用于 AD FS 服务器的所有 GPO 仅适用于它们,而不适用于任何其他服务器。这限制了通过 GPO 修改进行的潜在特权升级。
  • 确保已安装的证书受到保护以防被盗。不要将这些存储在网络上的共享中并设置日历提醒以确保它们在过期之前得到更新(过期的证书会破坏联合身份验证)。此外,我们建议在附加到 AD FS的硬件安全模块 (HSM)中保护签名密钥或证书。
  • 将日志记录设置为最高级别并将 AD FS(和安全)日志发送到 SIEM,以与 AD 身份验证以及 Azure AD(或类似)相关联。
  • 删除不必要的协议和 Windows 功能。
  • 为 AD FS 服务帐户使用长(> 25 个字符)和复杂的密码。我们建议使用组托管服务帐户 (gMSA)作为服务帐户,因为它通过自动管理它消除了随着时间的推移管理服务帐户密码的需要。
  • 更新到最新的 AD FS 版本以改进安全性和日志记录(一如既往,先测试)。
  • 与 Azure AD 联合时,请遵循使用 Azure AD保护和监视AD FS 信任的最佳做法。

检测

保护 AD FS 服务器是缓解 NOBELIUM 攻击的关键。在 AD FS 服务器上检测和阻止恶意软件、攻击者活动和其他恶意工件可能会破坏已知 NOBELIUM 攻击链中的关键步骤。Microsoft Defender 防病毒软件将本博客中讨论的新 NOBELIUM 组件检测为以下恶意软件:

  • 加载程序:Trojan:Win32/FoggyWeb.A!dha
  • 后门:Trojan:MSIL/FoggyWeb.A!dha

微软 365后卫

Microsoft Defender for Endpoint 中的终结点检测和响应 (EDR) 功能可检测与此恶意软件相关的恶意行为,这些恶意行为显示为具有以下标题的警报:

  • ADFS 服务加载了可疑的 DLL
  • 可疑服务启动
  • 可疑文件被丢弃
img

Azure AD 身份保护

也可以使用 Azure AD 身份保护在云中检测到这种攻击。建议您监视“令牌颁发者异常”检测的Azure AD 身份保护风险检测报告。此检测会查找呈现给 Azure AD 租户的 SAML 令牌中的异常情况。

高级狩猎查询

用于终结点的 Microsoft Defender

要查找相关活动,请在微软 365后卫:

DeviceImageLoadEvents| where FolderPath has @"C:\Windows\ADFS"where FileName has @"version.dll"

Azure Sentinel

Azure Sentinel 客户可以使用以下检测查询来查找此活动:

检测查询:https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/Nobelium_FoggyWeb.yaml

IOC 文件:https://github.com/Azure/Azure-Sentinel/tree/master/Sample Data/Feeds/FoggyWebIOC.csv

译文申明

  • 文章来源为近期阅读文章,质量尚可的,大部分较新,但也可能有老文章。
  • 开卷有益,不求甚解,不需面面俱到,能学到一个小技巧就赚了。
  • 译文仅供参考,具体内容表达以及含义, 以原文为准 (译文来自自动翻译)
  • 如英文不错的,尽量阅读原文。(点击原文跳转)
  • 每日早读基本自动化发布(不定期删除),这是一项测试

最新动态: Follow Me

微信/微博:red4blue

公众号/知乎:blueteams



文章来源: https://mp.weixin.qq.com/s?__biz=MzU0MDcyMTMxOQ==&mid=2247487294&idx=3&sn=ca5a05c3ecfc61287a393ca286461834&chksm=fb35a6f6cc422fe01e0b334cdf3b0d9543f9ffd2837a6076ffcc41eee5f4789d0cca3f968bea#rd
如有侵权请联系:admin#unsafe.sh