MagicWeb:NOBELIUM 以任何人身份进行身份验证的入侵后技巧
微软安全研究人员发现了一种我们称之为 MagicWeb 的入侵后功能,我们跟踪为 NOBELIUM 的威胁参与者使用该功能来维持对被入侵环境的持久访问。NOBELIUM 保持高度活跃,同时针对美国、欧洲和中亚的政府组织、非政府组织 (NGO)、政府间组织 (IGO) 和智库开展多项活动。Microsoft 威胁情报中心 (MSTIC) 评估说,MagicWeb 很可能是在持续入侵期间部署的,并且 NOBELIUM 可能利用它在可能抢先驱逐的战略补救步骤期间保持访问。
NOBELIUM 使用滥用身份和凭据访问作为维持持久性的方法,而像 MagicWeb 这样的专门功能对攻击者来说并不新鲜:2021 年 9 月,微软披露了一种名为FoggyWeb的后利用功能,其方法和意图类似于 MagicWeb。FoggyWeb 能够泄露受感染 AD FS 服务器的配置数据库,解密 令牌签名证书和令牌解密证书,以及下载和执行其他恶意软件组件。MagicWeb 通过直接促进秘密访问超越了 FoggyWeb 的收集功能。MagicWeb 是一个恶意 DLL,它允许操纵 Active Directory 联合服务 (AD FS) 服务器生成的令牌中传递的声明。它操纵用于身份验证的用户身份验证证书,而不是在 Golden SAML 等攻击中使用的签名证书。
NOBELIUM 能够通过首先获得对高特权凭据的访问权限并横向移动以获得对 AD FS 系统的管理权限来部署 MagicWeb。这不是供应链攻击。攻击者拥有 AD FS 系统的管理员访问权限,并将合法的 DLL 替换为他们自己的恶意 DLL,导致 AD FS 加载恶意软件而不是合法的二进制文件。该后门是由 Microsoft 的检测和响应团队 (DART) 与 MSTIC 和微软 365Defender Research 正在进行的事件响应调查期间。Microsoft 在征得客户同意的情况下共享此信息。在本次调查时,MagicWeb 似乎具有高度针对性。
与域控制器一样,AD FS 服务器可以对用户进行身份验证,因此应该受到同样高级别的安全性对待。客户可以通过实施包括AD FS 强化指南在内的整体安全策略来防御 MagicWeb 和其他后门。在这一特定发现的情况下,MagicWeb 是一个更大的入侵链中的一个步骤,它提供了独特的检测和预防方案。
对于 AD FS 等所有关键基础架构,确保攻击者无法获得管理访问权限非常重要。一旦攻击者获得管理访问权限,他们就有许多选项可以进一步破坏系统、活动混淆和持久性。我们建议隔离任何此类基础架构,仅由专用管理员帐户访问,并定期监控任何更改。可以防止这种攻击和其他攻击的其他安全措施包括防止横向移动的凭证卫生。AD FS 是本地服务器,与所有本地服务器一样,部署可能会过时和/或未打补丁,并且可能会受到本地环境妥协和横向移动的影响。由于这些原因,迁移到基于云的身份解决方案,例如 Azure Active Directory推荐使用联合身份验证,因为它提供了强大的安全性。有关详细信息,请参阅下面的缓解部分。尽管我们评估该功能的使用有限,但 Microsoft 预计其他参与者可能会采用类似的方法,因此建议客户查看此博客中提供的强化和缓解指南。
MagicWeb 如何颠覆身份验证
MagicWeb 是一种攻击后恶意软件,只有在获得对环境的高度特权访问并横向移动到 AD FS 服务器后,才能由攻击者部署。为了实现通过验证 AD FS 服务器上任何用户帐户的身份验证来维持对环境的持久访问的目标,NOBELIUM 通过复制AD FS 操作中使用的合法Microsoft.IdentityServer.Diagnostics.dll文件创建了一个后门 DLL。此文件的合法版本是目录签名的由 Microsoft 提供,通常由 AD FS 服务器在启动时加载以提供调试功能。NOBELIUM 文件的后门版本是未签名的。威胁参与者的高权限访问允许他们访问 AD FS 服务器,这意味着他们可以在环境中执行任意数量的操作,但他们特别选择以 AD FS 服务器为目标,以促进他们在操作期间实现持久性和信息盗窃的目标.
在通过特权提升和横向移动获得对 AD FS 服务器的管理访问权限后,可以通过编辑C:\Windows\AD FS\Microsoft.IdentityServer将 NOBELIUM 的恶意Microsoft.IdentityServer.Diagnostics.dll 加载到 AD FS 进程中。 Servicehost.exe.config指定不同的公共令牌,该令牌控制在 AD FS 进程启动时加载的内容。因为 AD FS 是一个 .NET 应用程序,它从全局程序集缓存加载配置文件中指定的 DLL(GAC)。通过更改配置中的令牌,攻击者指示 AD FS 加载恶意 DLL。MagicWeb 对声明的拦截和操纵使攻击者能够生成令牌,允许攻击者绕过 AD FS 策略(角色策略、设备策略和网络策略)并以任何用户身份登录,包括多因素身份验证 (MFA) .
图 1. C:\Windows\AD FS\Microsoft.IdentityServer.Servicehost.exe.config被设置为加载
Microsoft.IdentityServer.Diagnostics.dll
图 2. NOBELIUM 使用与合法Microsoft.IdentityServer.Diagnostics.dll不同的公共令牌
告诉 AD FS 在 GAC 中查找不同的文件
图 3. Microsoft.IdentityServer.Servicehost.exe.config的特写
显示 MagicWeb 的恶意PublicKeyToken与合法版本 DLL的PublicKeyToken相比
图 4. 感染 MagicWeb 的服务器上 GAC 中的目录
恶意的Microsoft.IdentityServer.Diagnostics.dll文件和合法的文件位于不同的目录中
要了解 NOBELIUM 如何使用 MagicWeb 恶意软件破坏 AD FS 进程,了解 AD FS 声明的工作原理非常重要。AD FS 将使用单一安全或企业边界内可用的单点登录功能的能力扩展到面向 Internet 的应用程序,以便在访问组织的基于 Web 的应用程序时为客户、合作伙伴和供应商提供简化的用户体验。AD FS 依赖于基于声明的身份验证来验证用户的身份及其授权声明。这些声明被打包成一个可用于身份验证的令牌。MagicWeb 将自身注入到声明过程中,以执行 AD FS 服务器正常角色之外的恶意操作。
图 5. AD FS 声明管道如何为进入联合应用程序的用户颁发令牌
安全断言标记语言 (SAML) 使用 x509 证书在身份提供者和服务之间建立信任关系,并对令牌进行签名和解密。这些 x509 证书包含增强密钥使用 (EKU) 值,这些值指定证书应用于哪些应用程序。
例如,包含对象标识符 (OID) 值为 1.3.6.1.4.1.311.20.2.2 的 EKU 将允许使用智能卡登录。组织可以创建自定义 OID 以进一步缩小证书使用范围。
MagicWeb 的身份验证绕过来自在对指定用户主体名称的身份验证请求期间传递在 MagicWeb 恶意软件中硬编码的非标准增强密钥使用 OID。当遇到这个唯一的硬编码 OID 值时,MagicWeb 将导致身份验证请求绕过所有标准 AD FS 进程(包括 MFA 检查)并验证用户的声明。MagicWeb 正在操纵在 SAML 登录中使用的用户身份验证证书,而不是在 Golden SAML 等攻击中使用的 SAML 声明的签名证书:
图 6. MagicWeb 接受的用户证书示例
“未知密钥用法”下突出显示的数字是硬编码到 MagicWeb 中的两个 OID 之一
图 7. 用户证书链示例,显示无效数字签名但仍可用于身份验证
NOBELIUM 对每个目标使用独特的贸易技术,因此 OID 和公共令牌很可能也是每个目标唯一的。我们在本报告中编辑了这些 OID 和令牌。有关如何查找与此攻击相关的变体的信息,请参阅狩猎指南部分。
如何减轻这种威胁
NOBELIUM 部署 MagicWeb 的能力取决于能够访问对 AD FS 服务器具有管理访问权限的高特权凭据,从而使他们能够在他们有权访问的系统上执行他们想要执行的任何恶意活动。
将 AD FS 服务器视为第 0 层资产至关重要,使用与域控制器或其他关键安全基础架构相同的保护来保护它们。AD FS 服务器向配置的依赖方提供身份验证,因此获得对 AD FS 服务器的管理访问权限的攻击者可以完全控制对配置的依赖方的身份验证(包括配置为使用 AD FS 服务器的 Azure AD 租户)。实践凭证卫生对于保护和防止高特权管理员帐户的暴露至关重要。这尤其适用于更容易受到攻击的系统,例如具有登录限制等控件的工作站,并通过 Windows 防火墙等控件防止横向移动到这些系统。
建议迁移到 Azure Active Directory (Azure AD) 身份验证,以降低本地入侵横向移动到身份验证服务器的风险。客户可以在迁移时使用以下参考:
- 使用活动报告将 AD FS 应用移动到 Azure AD
-
高级狩猎查询
推荐狩猎指南
在您的公钥基础设施 (PKI) 环境中拥有库存证书颁发策略,包括环境中使用的所有 EKU 属性,并与已知的 OID 值进行比较。
- 通过启用 AD FS详细日志记录来搜索 Windows 事件日志。启用安全审核以允许收集AD FS 事件日志,并专门查找事件 ID 501 。此事件指定声明中的所有 EKU 属性。搜索这些日志以查找您的 PKI 基础架构未配置为发布的 EKU 值。
- 在系统上的 GAC 或 AD FS 目录中查找未由 Microsoft 签名的可移植可执行文件,并检查这些文件或提交它们以供分析。
对您的排除设置执行审核,以确保 AD FS 和 GAC 包含在扫描中。由于性能下降问题,许多组织将 AD FS 目录排除在安全软件扫描之外。
微软哨兵
为 ADFS启用详细模式日志记录的Microsoft Sentinel 客户可以使用此查询来查找可疑 OID:https ://github.com/Azure/Azure-Sentinel/tree/master/Detections/SecurityEvent/ADFSAbnormalEnhancedKeyUsageAttribute-OID.yaml 。
注意:使用正确的事件集合在 Sentinel 中启用正确的连接器很重要。有关 Sentinel 中 AD FS 审核日志收集的更多详细信息,请参阅此帖子。在 GAC 中搜索未签名的文件
合法的Microsoft.IdentityServer.Diagnostics.dll是由 Microsoft签名的目录。目录签名是 Windows 用于验证代码完整性的一种方法,与Authenticode不同,它用于脱机验证,而不是仅运行签名代码的运行时强制。此文件上的目录签名意味着该文件可能在文件属性窗格以及文件完整性检查器、安全工具和在线恶意软件存储库中似乎未签名。下面的脚本允许您查找未签名的二进制文件并了解目录签名的二进制文件和 Authenticode 签名的二进制文件。
使用 Microsoft 365 Defender 在 GAC 中显示未签名的 DLL
此查询显示过去 60 天内创建的 GAC 文件夹中的未签名 DLL:DeviceFileEvents
| where Timestamp between( ago(60d)..now() )
| where FolderPath has @"C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.IdentityServer."
and FileName endswith ".dll"
| join (
DeviceFileCertificateInfo
| where not(IsSigned)
) on SHA1
使用 PowerShell 在 GAC 中枚举非 Microsoft 签名的 DLL
下面是一个示例脚本,可用于枚举相关 GAC 文件夹中非 Microsoft 签名的 DLL,其中servers.txt是您希望扫描的服务器列表。因为合法的Microsoft.IdentityServer.Diagnostics.dll是目录签名的,所以在查看文件属性时不会出现签名,但会在 PowerShell 查询和加载 DLL 时显示:$servers = get-content -Path (path to file)\servers.txt
Foreach ($server in $servers)
{
Write-Output "Processing server: $server"
Invoke-Command -ComputerName $server
{
Get-ChildItem -Filter "*.dll" -Recurse "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\" | get-authenticodesignature | ft
}
}
检测
Microsoft Defender 防病毒软件
Microsoft Defender 防病毒使用以下恶意软件名称提供此威胁的检测:
-
Microsoft Defender for Endpoint
Microsoft Defender for Endpoint 客户可能会看到以下警报,表示可能受到攻击:
ADFS persistent backdoor detected
IoCs
微软目前没有在这个 NOBELIUM 活动上分享 IOC。然而,NOBELIUM 经常为每个战役定制基础设施和功能,从而在发现其战役特定属性时将运营风险降至最低。如果在您的环境中识别出 MagicWeb,则不太可能匹配来自其他目标的任何静态 IOC,例如 SHA-256 值。建议使用上面提供的狩猎指南来调查您的环境。
MagicWeb的技术分析
NOBELIUM 通过将恶意代码添加到Microsoft.IdentityServer.Diagnostics命名空间/类型中的 TraceLog 类来修改合法的Microsoft.IdentityServer.Diagnostics.dll 。
来自合法Microsoft.IdentityServer.Diagnostics.dll的 TraceLog 类的标头部分如下所示:
图 8. 来自合法Microsoft.IdentityServer.Diagnostics.dll的Microsoft.IdentityServer.Diagnostics命名空间/类型的 TraceLog 类的标头部分
同时,来自 NOBELIUM 的Microsoft.IdentityServer.Diagnostics.dll后门版本的 TraceLog 类的标头部分如下所示:
图 9.来自 NOBELIUM 的Microsoft.IdentityServer.Diagnostics.dll后门版本的Microsoft.IdentityServer.Diagnostics命名空间的 TraceLog 类的标头部分
在代码的后门版本中,如上图所示,NOBELIUM 为 TraceLog 类添加了一个静态构造函数。静态构造函数用于初始化任何静态数据,或执行只需要执行一次的特定操作。它在创建第一个实例或引用任何静态成员之前自动调用。
恶意静态构造函数在 TraceLog 类的第一个实例创建之前执行一次。鉴于 TraceLog 类的新实例是在此 DLL 的不同位置创建的,恶意静态构造函数的执行保证会在第一次加载 DLL 时发生(这将在 AD FS 服务器启动时)在上述对Microsoft.IdentityServer.Servicehost.exe.config进行恶意更改之后)。
NOBELIUM 的恶意静态构造函数包含对名为AuthLog的类的Initialize()方法的引用:
图 10.恶意静态构造函数中名为AuthLog的类对Initialize()方法的引用
AuthLog类是一个全新的恶意类,由 NOBELIUM 添加到 DLL 中。
图 11. AuthLog类的Initialize()方法
如上所示,Initialize()方法引用了一个名为RuntimeHelper的类,这是演员添加到 DLL 中的另一个类。RuntimeHelper类及其OverloadMethod()方法的主要目的是在运行时Hook合法的 AD FS 相关方法。通过Hook合法的 AD FS 方法,后门能够拦截对合法方法的调用,以调用其自己的自定义方法。
上面的屏幕截图显示了以下被 MagicWeb Hook的合法 AD FS 方法:
目标程序集/DLL | 目标类型 | Hook的目标方法 | 恶意Hook方法(演员介绍) |
---|---|---|---|
Microsoft.IdentityServer.IdentityModel.dll | Microsoft.IdentityModel.X509CertificateChain | Build | BeginBuild |
Microsoft.IdentityServer.WebHost.dll | Microsoft.IdentityServer.WebHost.WrappedHttpListenerRequest | GetClientCertificate | BeginGetClientCertificate |
Microsoft.IdentityServer.WebHost.dll | Microsoft.IdentityServer.WebHost.Proxy.ProxyConfigurationData | EndpointConfiguration | BeginEndpointConfiguration |
Microsoft.IdentityServer.Service.dll | Microsoft.IdentityServer.Service.IssuancePipeline.PolicyEngine | ProcessClaims | BeginProcessClaims |
Hook方法:BeginBuild()
MagicWeb 的BeginBuild()方法用于Hook合法的目标方法Build()(来自Microsoft.IdentityServer.IdentityModel.dll):
图 12. MagicWeb 的BeginBuild()方法
BeginBuild()方法首先调用 MagicWeb 的辅助方法ValidateX509Extensions ()。
如果辅助方法ValidateX509Extensions()返回 true,则BeginBuild()返回 true。
如果ValidateX509Extensions()返回 false,或者调用ValidateX509Extensions()引发异常,则BeginBuild()调用并返回Microsoft.IdentityServer.IdentityModel.dll中合法的Build()方法返回的值。
这意味着在 来自合法Microsoft.IdentityServer.IdentityModel.dll的合法目标方法Build()有机会检查/构建证书之前,MagicWeb 的钩子方法首先检查证书并在辅助方法ValidateX509Extensions()返回 true 时返回 true .
这允许攻击者通过引入在调用合法Build()方法之前调用的自定义证书检查/构建方法来破坏正常的证书检查/构建过程。
辅助方法:ValidateX509Extensions()
MagicWeb 的辅助方法ValidateX509Extensions()由BeginBuild()和其他方法调用:
图 13. 辅助方法ValidateX509Extensions()
如果传递给方法的 X509 证书为 null 或未设置 Microsoft Cryptographic API 证书上下文句柄/指针,ValidateX509Extensions()将返回 false。
接下来,该方法枚举传递给该方法的 X509 证书中的扩展。如果枚举扩展的类型为X509EnhancedKeyUsageExtension,则该方法迭代扩展的 OID,计算每个 OID 的 MD5 哈希(使用利用 .NET MD5类的自定义哈希计算帮助器方法ComputeHash() )。
如果 OID 的 MD5 哈希值与以下两个硬编码 MD5 值之一匹配,则该方法返回 true(此方法用于检查扩展中是否存在以下两个 OID 值之一):
- 67F5BD28A842A1C9[REDACTED](MD5哈希值对应OID值 1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[REDACTED].[REDACTED].[REDACTED].[REDACTED])
- 6E3466296D2F63D[REDACTED] (MD5哈希值对应OID值1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[REDACTED].[REDACTED].[REDACTED].[REDACTED])
如果不存在任何 OID 值,则该方法返回 false。
如果传递给该方法的证书包含上面列出的两个魔术 OID 值之一,则此帮助程序方法返回 true。
Hook方法:BeginGetClientCertificate()
图 14. MagicWeb 的BeginGetClientCertificate()方法,用于Hook合法目标方法GetClientCertificate()(来自Microsoft.IdentityServer.WebHost.dll)
要检索客户端的 X509 证书,此方法首先从Microsoft.IdentityServer.WebHost.dll调用合法的GetClientCertificate()方法。接下来,钩子方法调用辅助方法ValidateX509Extensions()来确定客户端证书是否包含两个“神奇”OID 值之一。如果客户端证书包含两个 OID 值之一,则Hook方法:
- 从当前对象中获取_adapter字段
- 从_adapter对象中获取_request字段
- 将m_ClientCertificateError字段(来自_request对象)的值设置为 0
这意味着无论合法方法GetClientCertificate()(来自Microsoft.IdentityServer.WebHost.dll)将m_ClientCertificateError字段设置为什么,如果客户端证书包含一个神奇的 OID 值,则Hook方法会覆盖或设置m_ClientCertificateError字段0。
通过使用这种技术,钩子方法似乎正在影响应用程序的正常行为,以将无效的客户端证书视为有效证书或接受该证书。
Hook方法:BeginProcessClaims()
图 15. MagicWeb 的BeginProcessClaims()方法,用于Hook合法目标方法ProcessClaims()
(来自Microsoft.IdentityServer.Service.dll)
hook 方法首先通过调用AuthLog类的ProcessClaims()方法间接调用合法的ProcessClaims()方法。
在图 16 的第 198 行,钩子方法调用 MagicWeb 的辅助方法GetClaims(),传入通过调用合法ProcessClaims()方法返回的已处理身份对象。
图 16. GetClaims()辅助方法
如上所示,GetClaims()方法接受一个身份对象作为参数。然后,该方法使用从RuntimeHelper的名为types的静态字段/数组中获得的值初始化三个名为type、type2和type3的变量:
图 17. 用值初始化的三个变量
类型字段包含以下值:
图 18.类型字段中的值
上面的assemblyByName2变量包含一个代表合法程序集Microsoft.IdentityServer.IdentityModel.dll的程序集对象(如果尚未加载,则RuntimeHelper类将程序集加载到当前应用程序域中)。通过调用GetType()方法,RunHelper使用来自Microsoft.IdentityServer.IdentityModel.dll程序集的 .NET 类型初始化类型字段/数组的成员。
返回到GetClaims()方法和 type 、 type2 和 type3 的初始化,变量type 、 type2和type3使用来自Microsoft.IdentityServer.IdentityModel.dll的以下类型对象进行初始化:
- tyype: Microsoft.IdentityModel.Claims.IClaimsIdentity类型对象
- type2: Microsoft.IdentityModel.Claims.ClaimCollection类型对象
- type3: Microsoft.IdentityModel.Claims.Claim类型对象
接下来,GetClaims()方法检索Microsoft.IdentityModel.Claims.IclaimsIdentity标识对象的Claims属性。它还检索存在于Claims属性中的声明数(类型为Microsoft.IdentityModel.Claims.ClaimCollection ):
图 19. GetClaims()检索 Claims 属性
GetClaims()然后枚举声明(类型为Microsoft.IdentityModel.Claims.Claim),检索包含每个声明和相应声明类型的字符串:
图 20. GetClaims()枚举声明、检索字符串并存储在列表中
如上所示,声明字符串和声明类型字符串随后存储在名为list的列表中。然后,此声明列表及其相应声明类型将返回给GetClaims()方法的调用者BeginProcessClaims()。
返回到BeginProcessClaims()方法,在使用GetClaims()方法检索声明后,钩子方法BeginProcessClaims()搜索声明列表中是否存在声明类型为http://schemas.microsoft.com/claims/的声明授权方法参考:
图 21. BeginProcessClaims()在声明列表中搜索特定声明
如上面第 198 行所示, http: //schemas.microsoft.com/claims/authnmethodsreferences类型的声明(如果有)存储在名为list的列表中。如果http://schemas.microsoft.com/claims/authnmethodsreferences类型的声明存在并且其值设置为http://schemas.microsoft.com/claims/multipleauthn,则钩子方法返回合法返回的 IclaimsIdentity对象钩子方法第 191 行的目标方法ProcessClaims()(来自Microsoft.IdentityServer.Service.dll)。
此行为确保如果 MFA 已满足,则Hook方法仅充当传递方法,并且不会影响索赔处理管道的正常行为。
如果http://schemas.microsoft.com/claims/authnmethodsreferences类型的声明不存在或其值未设置为http://schemas.microsoft.com/claims/multipleauthn,则Hook方法继续执行其他检查对未处理 的声明(即传递给钩子方法的未处理标识对象标识中包含的声明)。再次,钩子方法通过调用GetClaims()辅助方法获取声明列表。如上所述,不是使用通过调用合法ProcessClaims()返回的已处理身份对象调用GetClaims()辅助方法方法(存储在第 191 行的结果变量中),钩子方法调用GetClaims()辅助方法,并将未处理的标识对象标识传递给钩子方法:
图 22. 调用GetClaims()的钩子方法
在第 204 行,钩子方法枚举每个声明的值,并使用ComputeHash()辅助方法计算每个声明值的 MD5 哈希值(来自未处理的身份对象)。然后它检查任何声明的 MD5 值是否等于 MD5 哈希值6E3466296D2F63DE[REDACTED]。此哈希值是名为oidMFAHashes的硬编码哈希列表的唯一元素(也就是说,此列表可以扩展以包含其他感兴趣的哈希值):
图 23. 包含魔法 OID 值的 MD5 哈希值的硬编码哈希列表a
如果没有任何声明的 MD5 哈希值为6E3466296D2F63DE[REDACTED],则在第 206 行,该方法仅返回由合法目标方法ProcessClaims()(来自Microsoft.IdentityServer.Service.dll)返回的已处理身份对象钩子方法的第 191 行。如前所述,哈希值6E3466296D2F63DE[REDACTED]对应于 OID 值1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[REDACTED].[REDACTED].[REDACTED].[REDACTED]。
因此,钩子方法会枚举声明,如果声明中不存在值为1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[REDACTED].[REDACTED].[REDACTED].[REDACTED]的声明列表中,钩子方法只是充当传递方法,不会影响索赔处理管道的正常行为。
如果在执行周期中此时钩子方法尚未返回,则意味着其中一个声明包含 OID 值1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[已编辑].[已编辑]。[已编辑].[已编辑](否则,根据上面段落中描述的逻辑,钩子方法将返回)。
继续确认其中一个声明包含 OID 值1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[REDACTED].[REDACTED].[REDACTED].[REDACTED],钩子方法继续执行以下部分:代表 MagicWeb 的主要目的,执行声明注入。
图 24. 负责声明注入过程的代码主要部分
在描述负责声明注入过程的代码之前,重要的是要重新访问列表和声明变量中已经存储的内容:
- list:如前所述,钩子方法调用合法方法ProcessClaims()来处理传入的身份对象。然后将处理后的身份对象(存储在第 191 行的结果中)传递给GetClaims()辅助方法,以获取从处理后的身份对象中提取的声明类型/值对的列表(第 198 行)。在获得声明类型/值对后, http: //schemas.microsoft.com/claims/authnmethodsreferences类型的声明(如果有)存储在名为 list 的列表中(第198行)。
图 25.列表变量
声明:如上所述,此变量用于存储从未处理的身份对象中提取的声明类型/值对列表:
图 26.声明变量
考虑到这些信息(以及其中一个声明包含 OID 值1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419. [已编辑] . [已编辑] . [已编辑] . [已编辑]的事实),一次这里又是声明注入代码的第一部分:
图 27. 声明注入代码的一部分
如上所示,如果list为空(即处理后的标识对象不包含http://schemas.microsoft.com/claims/authnmethodsreferences类型的声明类型/值对),则Hook方法转而使用声明(包含从未处理的标识对象中提取的所有声明类型/值对的列表 )并在声明列表中搜索类型为http://schemas.microsoft.com/claims/authnmethodsreferences的 声明类型/值对。如果声明列表包含一个或多个声明类型/值对类型http://schemas.microsoft.com/claims/authnmethodsreferences,钩子方法使用声明信息将http://schemas.microsoft.com/claims/authnmethodsreferences类型的相同声明添加到已处理的身份对象(上面的第 213 行)。
使用此方法,如果将标识对象传递给合法的ProcessClaims()方法后,合法方法没有返回http://schemas.microsoft.com/claims/authnmethodsreferences类型的声明,则Hook方法手动添加欺诈声明类型为http://schemas.microsoft.com/claims/authnmethodsreferences的声明列表返回给Hook的合法方法ProcessClaims()的调用者。
如上所示,要将欺诈性声明添加到声明列表中,钩子方法会调用一个名为AddClaim()的辅助方法。
图 28. 辅助方法
与辅助方法GetClaims()中的代码一样,AddClaims()使用以下类型对象初始化两个变量:
- 类型:Microsoft.IdentityModel.Claims.IClaimsIdentity类型对象
- type2:Microsoft.IdentityModel.Claims.ClaimCollection类型对象
在第 235 行,AddClaims()获取类型Microsoft.IdentityModel.Claims.Claim的构造函数并调用构造函数(从AddClaim()的调用者传入声明类型和值)以实例化新的Claim对象。
图 29.来自 Microsoft.IdentityModel.Claims.Claim的合法内部构造函数
来自Microsoft.IdentityModel.Claims.Claim的合法内部构造函数,由AddClaim()检索和调用,使用以下方法参数调用内部构造函数Claim (重载方法):
图 30. 内部构造函数 Claim
实例化一个新的Claim对象后,AddClaim()使用Microsoft.IdentityModel.Claims.ClaimCollection类型的Add()方法将新的声明添加到由其调用者传递给AddClaim()的标识对象中(在本例中,新的声明被添加到包含调用合法方法ProcessClaims()返回的声明列表的标识对象中)。
图 31. 来自Microsoft.IdentityModel.Claims.ClaimCollection类型的合法方法Add()
由AddClaim()调用(第 245 行)
重新访问Hook方法BeginProcessClaims()中的声明注入代码(并回想其中一个声明包含 OID 值1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419.[已编辑].[已编辑].[已编辑]这一事实].[REDACTED]),这是声明注入代码的第二部分:
图 32. 声明注入代码的第二部分
回想一下,该列表包含从已处理的身份对象中提取的http://schemas.microsoft.com/claims/authnmethodsreferences类型的声明类型/值对。如果列表中没有任何声明具有值http://schemas.microsoft.com/claims/multipleauthn,则Hook方法继续调用AddClaim()以添加类型为http://schemas.microsoft.com/的欺诈性声明Claims/authnmethodsreferences和价值http://schemas.microsoft.com/claims/multipleauthn到返回给钩子合法方法ProcessClaims()的调用者的声明列表。
使用上述欺诈性索赔注入技术,如果索赔的 Magic OID 值为1.3.6.1.4.1.311.21.8.868518.12957973.4869258.12250419。[已编辑] 。[已编辑] 。[已编辑] 。[已编辑]提交给 AD FS,无论合法的钩子方法ProcessClaims()如何处理声明,BeginProcessClaims()钩子函数确保返回值为http://schemas.microsoft.com/claims/multipleauthn的声明给合法的钩子方法ProcessClaims()的调用者。
Hook方法:BeginEndpointConfiguration()
后门BeginEndpointConfiguration()方法,用于Hook合法目标方法EndpointConfiguration()(来自Microsoft.IdentityServer.WebHost.dll)如下所示:
图 33. BeginEndpointConfiguration()方法
enumType 变量使用RuntimeHelper.types[0]进行初始化,它是一个Microsoft.IdentityServer.WebHost.Proxy.CertificateValidation类型对象。PropertyInfo变量propertyInfo、propertyInfo2和propertyInfo3使用从RuntimeHelper的“properties”字段/数组检索到的属性对象进行初始化:
- propertyInfo:来自Microsoft.IdentityServer.WebHost.Proxy.ProxyEndpoint的Microsoft.IdentityServer.WebHost.dll类型的CertificateValidation属性
- propertyInfo2 :来自Microsoft.IdentityServer.WebHost.Proxy.ProxyEndpoint的Microsoft.IdentityServer.WebHost.dll类型的路径属性
- propertyInfo3:来自Microsoft.IdentityServer.WebHost.Proxy.ProxyEndpointConfiguration的Microsoft.IdentityServer.WebHost.dll类型的端点属性
接下来,钩子方法检索调用合法EndpointConfiguration()方法的值对象的Endpoint属性的值。Endpoint属性包含ProxyEndpoint对象的集合。hook 方法枚举ProxyEndpoint对象,并且对于每个对象,它检查CertificateValidation枚举的值是否设置为表示“ SSL ”的“1 ”。如果ProxyEndpoint对象的CertificateValidation枚举设置为“1”/“SSL”,则在第 165 行,钩子方法将覆盖CertificateValidation的值带有“0”的枚举,表示“无”。为了确保反映更改,钩子方法然后用更新的Endpoint属性覆盖值对象的Endpoint属性,该属性包含被覆盖的 CertificateValidation枚举值(即,“SSL”被“None”覆盖)。
作为真正的钩子方法,在第 179 行,该方法调用合法的EndpointConfiguration()方法,但使用修改后的“值”对象。因此,当在 AD FS 的正常操作期间调用合法的EndpointConfiguration()方法时,此Hook方法会拦截调用,并且在将对象传递给调用合法的EndpointConfiguration()方法之前,它会覆盖 每个ProxyEndpoint的CertificateValidation值对象,然后它才调用合法的EndpointConfiguration()方法,但现在使用修改后 的CertificateValidation值,从“SSL”更改为“无”。
将CertificationValidation值覆盖为“无”(无论是“SSL”)的目的是允许 WAP 将带有特定恶意证书的请求传递给 AD FS,以进行进一步的身份验证处理。根据Microsoft.IdentityServer.ProxyService/TLSClientReqeustHandler ,如果CertificateValidation为“1”(“SSL”)并且客户端证书在验证期间出现错误,WAP 将停止从客户端向 AD FS 发送当前请求。
参考
- “我是 AD FS,你也可以:攻击 Active Directory 联合服务”,Austin Baker 和 Douglas Bienstock,2019 年 Troopers
- 了解关键 Active Directory 联合服务概念,Microsoft 文档