本文的翻译是专门为逆向工程课程的学生准备的。
总结
戴尔SecureWorks反威胁部门(CTU)的研究人员发现了恶意软件,该恶意软件绕过了实现单因素(仅密码)身份验证的Active Directory(AD)系统中的身份验证。 攻击者可以以任何用户身份使用自己选择的密码进行身份验证。 该恶意软件称为“骨架密钥”(通用密钥)。
CTU研究人员在使用单因素身份验证访问Web邮件和VPN的客户端网络上发现了万能钥匙,使攻击者可以不受阻碍地访问远程访问服务。 万能钥匙作为受害者的AD域控制器上的内存中的补丁程序进行部署,以允许攻击者以任何用户身份进行身份验证,而合法用户则继续照常进行身份验证。 万能钥匙身份验证旁路还允许物理访问攻击者登录并解锁对受感染的AD域控制器上的用户进行身份验证的系统。
发布时已知的唯一“骨架密钥”样本缺乏持久性-域控制器重新启动时必须重新部署它们。 CTU研究人员怀疑,由于域控制器上未检测到其他恶意软件,攻击者只能根据无法成功进行身份验证来识别重启。 重启后的八小时到八天之间,攻击者使用了受害者网络上已经部署的其他远程访问恶意软件,将万能钥匙重新部署到域控制器。
万能钥匙部署需要域管理员凭据。 CTU研究人员看到攻击者使用从关键任务服务器,管理员工作站和目标域控制器窃取的凭据来部署万能钥匙。
分析方法
最初,CTU研究人员在受感染的网络中观察到了一个名为ole64.dll的万能钥匙样本(请参见表1)。
表1.示例骨架密钥ole64.dll
。在研究
ole64.dll
,CTU研究人员在受害者网络的“中间主机”上发现了较旧版本的
msuta64.dll
(请参阅表2)。 中间主机是以前被恶意远程访问恶意软件破坏的任何系统。 此选项包括其他调试运算符,使Skeleton Key开发人员可以观察修补过程中涉及的内存地址。
表2.示例骨架密钥msuta64.dll
。攻击者使用以下算法将“万能钥匙”部署为64位DLL文件:
- 将万能钥匙DLL文件下载到受害网络上暂存主机上的暂存目录中。 CTU研究人员观察到与骨架密钥DLL文件关联的三个文件名:ole64.dll,ole.dll和msuta64.dll。 Windows系统包括合法的ole32.dll文件,但与该恶意软件无关。
- 尝试使用被盗的域管理员凭据列表访问域控制器上的管理资源。
- 如果被盗的凭据不再有效,请使用密码盗窃工具从以下位置之一提取明文形式的域管理员密码:这表明您熟悉受害者的环境:
- 受害者网络上另一台可用服务器的内存
- 域管理员职位
- 目标域控制器
- 使用有效的域管理员凭据将骨架密钥DLL复制到目标域控制器上的C:\ WINDOWS \ system32 \。
- 使用PsExec实用程序通过rundll32命令在目标域控制器上远程运行“骨架密钥DLL”文件。 攻击者选择的密码格式为NTLM哈希密码,并且不会以明文形式显示。 部署万能钥匙后,攻击者可以使用配置的
NTLM: psexec -accepteula \\% TARGET-DC% rundll32 < DLL> ii < NTLM>
密码哈希对任何用户进行身份验证NTLM: psexec -accepteula \\% TARGET-DC% rundll32 < DLL> ii < NTLM>
- 从目标域控制器上的C:\ WINDOWS \ system32 \中删除Skeleton Key DLL文件。
- 从过渡主机上的登台目录中删除万能钥匙DLL文件。
- 使用“ net use”命令以及与配置的NTLM哈希匹配的AD帐户和密码,测试万能钥匙的成功部署。
CTU研究人员发现了一种嵌入式密码模式,这表明一群攻击者在几个组织中部署了万能钥匙。
在Windows环境中,可以通过警告实用程序生成的Windows事件来检测PsExec的使用。 在目标域控制器上观察到的以下事件标识符注册了安装其服务,启动该服务以及停止该服务的PsExec工具。 每次使用PsExec时都会生成这些事件,因此需要对事件进行额外的分析以确定它们是恶意的还是合法的:
- AD域控制器上发生意外的PSEXESVC服务安装事件(事件代码7045):
日志名称 :系统
资料来源 :服务控制经理
摘要 :服务已安装在系统上。
服务文件名 :
%SystemRoot%\PSEXESVC.exe
- AD域控制器上发生意外的PSEXESVC服务启动/停止事件(事件代码7036):
日志名称 :系统
资料来源 :服务控制经理
总结 :
- “ PSEXESVC服务正在运行。”
- “ PSEXESVC服务已转换为停止状态。”
作为处于运行状态的万能钥匙,您需要执行以下任务:
- 检查以下兼容的Windows 64位版本之一。 该恶意软件与32位版本的Windows或Windows Server 2012(6.2)开始的Windows Server版本不兼容。
- 6.1(Windows 2008 R2)
- 6.0(Windows Server 2008)
- 5.2(Windows 2003 R2)
- 使用SeDebugPrivilege函数获得必要的管理员权限,以写入本地安全子系统(LSASS)服务进程。 此过程控制AD域的安全功能,包括用户帐户身份验证。
- 列出可用的进程以获取LSASS进程句柄。
- 获取与身份验证相关的功能的地址,该地址将被修复:
- CDLocateCSystem-位于
cryptdll.dll
- SamIRetrieveMultiplePrimaryCredentials-位于
samsrv.dll
- SamIRetrievePrimaryCredentials-位于
samsrv.dll
- 在步骤1的兼容性检查期间,使用全局变量集为特定的OS进行设置。
- 使用OpenProcess函数获取LSASS进程句柄。
- 保留并分配必要的内存空间,以编辑和修补LSASS进程的内存。
- 基于操作系统补丁相关功能:
- CDLocateCSystem(Windows的所有兼容版本)
- SamIRetrieveMultiplePrimaryCredentials(仅Windows 2008 R2(6.1))
- SamIRetrievePrimaryCredentials(Windows的所有兼容版本,Windows 2008 R2(6.1)除外)
要修复每个功能:
- 调用VirtualProtectEx函数以更改内存保护,以允许写入所需的内存分配(PAGE_EXECUTE_READWRITE,0x40)。 此步骤使您可以更新内存中的功能代码。
- 调用WriteProcessMemory函数以更改目标函数的地址,使其指向更正的代码。 此更改导致函数调用使用补丁。
- 通过使用原始内存保护标志调用VirtualProtectEx,可以恢复原始内存保护。 必须执行此步骤,以避免可疑分配用于记录和执行的内存。
修补后,攻击者可以使用部署期间配置的万能钥匙密码以任何域用户身份登录。 合法用户仍可以使用自己的密码登录。 此身份验证绕过适用于所有使用AD单因素身份验证的服务,例如Webmail和VPN,还允许攻击者具有对受感染系统的物理访问权,可以通过在键盘上输入嵌入式密码来解锁计算机。
可能与域复制问题相关
恶意代码万能钥匙不会传输网络流量,这会使基于网络的发现无效。 但是,此恶意软件已经牵涉到可能表明感染的域复制问题。 在CTU研究人员检测到每次部署Skeleton Key恶意软件后不久,域控制器都遇到了Microsoft支持部门无法解释或解决的复制问题,最终需要重新启动才能解决这些问题。 这些重新启动消除了“万能钥匙”身份验证绕行,因为该恶意软件没有持久性机制。 在图。 图1显示了这些重新启动的时间表,以及入侵者随后盗窃密码,横向扩展和部署万能钥匙的过程。 重定位通常在重新启动后的几个小时或几天内发生。
图1. CTU研究人员观察到的部署和重启关系,2014年4月至7月(来源:Dell SecureWorks)应对措施
恶意代码“骨架密钥”会绕过身份验证,并且不会生成网络流量。 结果,网络入侵检测和防御系统(IDS / IPS)将无法检测到此威胁。 但是,CTU研究人员在
附录A中写下了YARA签名,以发现万能钥匙DLL及其输入到LSASS过程存储器中的代码。
威胁指标
表3中的威胁指示器可用于检测与万能钥匙恶意软件有关的活动。
表3.万能钥匙的指示器。结论
CTU研究小组建议组织实施以下“万能钥匙”安全功能:
- 所有远程访问解决方案(包括VPN和远程电子邮件)的多因素身份验证均不允许威胁参与者绕过单因素身份验证或使用被盗的静态凭据进行身份验证。
- 工作站和服务器(包括AD域控制器)上的进程创建审核日志可以检测“万能钥匙”部署。 特别是,组织应寻找以下工件:
- 意外的PsExec.exe进程和PsExec“ -accepteula”命令行参数的使用
- 意外的rundll32.exe进程
- 处理类似于NTLM哈希码的参数(32个字符,包含数字0-9和AF字符)
- 在AD域控制器上监视Windows Service Manager事件可以为PSEXESVC PsExec服务检测意外的服务安装事件(事件代码7045)和启动/停止事件(事件代码7036)。
附录A-YARA签名
下面的YARA签名通过扫描Active Directory域控制器(可能包含“骨架密钥”)的可疑文件或内存转储来检测系统中是否存在“骨架密钥”。
rule skeleton_key_patcher { strings: $target_process = "lsass.exe" wide $dll1 = "cryptdll.dll" $dll2 = "samsrv.dll" $name = "HookDC.dll" $patched1 = "CDLocateCSystem" $patched2 = "SamIRetrievePrimaryCredentials" $patched3 = "SamIRetrieveMultiplePrimaryCredentials" condition: all of them } rule skeleton_key_injected_code { strings: $injected = { 33 C0 85 C9 0F 95 C0 48 8B 8C 24 40 01 00 00 48 33 CC E8 4D 02 00 00 48 81 C4 58 01 00 00 C3 } $patch_CDLocateCSystem = { 48 89 5C 24 08 48 89 74 24 10 57 48 83 EC 20 48 8B FA 8B F1 E8 ?? ?? ?? ?? 48 8B D7 8B CE 48 8B D8 FF 50 10 44 8B D8 85 C0 0F 88 A5 00 00 00 48 85 FF 0F 84 9C 00 00 00 83 FE 17 0F 85 93 00 00 00 48 8B 07 48 85 C0 0F 84 84 00 00 00 48 83 BB 48 01 00 00 00 75 73 48 89 83 48 01 00 00 33 D2 } $patch_SamIRetrievePrimaryCredential = { 48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 49 8B F9 49 8B F0 48 8B DA 48 8B E9 48 85 D2 74 2A 48 8B 42 08 48 85 C0 74 21 66 83 3A 26 75 1B 66 83 38 4B 75 15 66 83 78 0E 73 75 0E 66 83 78 1E 4B 75 07 B8 A1 02 00 C0 EB 14 E8 ?? ?? ?? ?? 4C 8B CF 4C 8B C6 48 8B D3 48 8B CD FF 50 18 48 8B 5C 24 30 48 8B 6C 24 38 48 8B 74 24 40 48 83 C4 20 5F C3 } $patch_SamIRetrieveMultiplePrimaryCredential = { 48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 41 8B F9 49 8B D8 8B F2 8B E9 4D 85 C0 74 2B 49 8B 40 08 48 85 C0 74 22 66 41 83 38 26 75 1B 66 83 38 4B 75 15 66 83 78 0E 73 75 0E 66 83 78 1E 4B 75 07 B8 A1 02 00 C0 EB 12 E8 ?? ?? ?? ?? 44 8B CF 4C 8B C3 8B D6 8B CD FF 50 20 48 8B 5C 24 30 48 8B 6C 24 38 48 8B 74 24 40 48 83 C4 20 5F C3 } condition: any of them }