章节9:Windows凭证理论

NTLM 认证

在之前的内容中,我们接触到了多种类型的凭证,包括了明文密码、NTLM 哈希、AES 256 密钥、NetNTLM 等。掌握明文密码显然是一项优势,然而,我们不是总能获得明文密码的,更多时候我们会得到 NTLM 哈希。如果用户设置了强密码,我们就无法破解 NTLM 哈希并快速恢复明文密码,但幸运的是,与许多其他类型的哈希不同,我们可以通过多种方式利用 NTLM 哈希进而实现认证。 

NTLM


我们之前讨论过了 Kerberos 身份认证,它是 NTLM 身份认证的后继者。Kerberos 认证是基于票据的,而 NTLM 认证则是基于质询响应的机制。NTLM 是一套 Microsoft 安全协议,用于验证用户身份并确保其活动的完整性和机密性,当客户端通过 IP 地址向服务器进行身份认证时所使用。虽然 Kerberos 协议是当今 AD 的默认身份认证协议,NTLM 认证仍被支持,一些应用程序仍然偏好 NTLM 身份认证,而且如果 Kerberos 在某些情况下无法对用户进行身份认证时,NTLM 将作为备份。

NTLM 身份认证协议由多个步骤组成,下面将对其进行深入说明。

1:用户访问客户端电脑,提供域名用户名密码。客户端计算出密码的哈希并将明文用户名发送到服务器。

2:服务器生成一个称为挑战的随机数,并将其发送回客户端。

3:客户端用用户密码的哈希对挑战进行加密,并将结果 (响应) 返回给服务器。

4:服务器域控制器发送用户名挑战响应

5:域控制器根据用户密码查找哈希,它比较加密的挑战。

6:服务器将响应发送回客户端,认证成功

image.png


SAM 安全账户管理器

安全帐户管理器 (SAM) 数据库以 NTLM 哈希格式存储本地 Windows 凭证。在本地登录期间,用户输入密码后,本地安全机构 (LSA) 通过根据存储在 SAM 中的数据验证凭证来验证登录尝试。当输入的密码的哈希与 SAM 中的 NTLM 哈希匹配时,登录成功。当我们在主机上得到了提升特权,我们就可以通过多种方式从 SAM 中提取凭证。在域环境中,本地帐户的凭证对我们来说可能看起来不那么令人兴奋。但是,考虑到密码重用的可能性,如果我们获得主机上本地管理员帐户的 NTLM 哈希或明文密码,域用户可能会在另一台主机上重用该凭证。一个实际生活中的例子可以是,某服务器管理员同时管理 2 个 SQL 数据库服务器,为了方便记忆,于是给这 2 台服务器设置了相同的本地管理员密码。

至于从 SAM 中导出哈希,我们有多种方法,分别如下。


通过工具在线导出

我们可以借助诸如 mimikatz 之类的工具在线导出 SAM 中的凭证,十分方便。我们需要获得一个受害主机的 SYSTEM 会话。

mimikatz

考虑到 Cobalt Strike 自带了 Mimikatz 的命令,我们可以直接使用内置的 mimikatz 导出 SAM 中的凭证。命令为 mimikatz lsadump::sam

不出所料,我们得到的都是本地帐号

image.png

C2 内置命令

导出 SAM 数据库中的凭证并不是 mimikatz 的独有功能,因此诸多 C2 也集成了导出 SAM 的内置命令,在 Cobalt Strike 中,也有这样的一个单独命令的存在,使用 hashdump 命令即可。

输出十分简洁明了。

image.png

Impacket 远程导出

Impacket 中的 secretdump.py 脚本可以在提供凭证后远程导出 SAM 中的凭证,通过远程注册表的方法。

image.png


离线导出

使用 mimikatz 之类的工具在线导出固然很方便,我们也可以将相关文件复制或导出,然后进行离线解析从而获得之中的凭证。

注册表复制

分别从注册表 HKLM\SAM 和 HKTM\SYSTEM 的位置拷贝 SAM 数据库和 SYSTEM。

reg save HKLM\SYSTEM C:\Windows\Tasks\SYSTEM
reg save HKLM\SAM C:\Windows\Tasks\SAM

image.png

image.png

image.png

为什么导出的是 SAM 与 SYSTEM 呢?SAM 用于存储本地账户的凭证,而SYSTEM 包含了用于解密 SAM 与 LSA 机密 (稍后会说) 的信息。

在这之后,我们可以通过多种工具来解密,例如 mimikatz,impacket 等。

image.png

 
拷贝 SAM 数据库文件

SAM 数据库的文件地址是 C:\Windows\System32\config\SAM,对应的 SYSTEM 则也在同目录下。我们是否可以直接复制/下载该文件,然后通过工具来解密呢?

image.png

实际上是不可行的,因为该文件被锁定了,无法对其进行读和写。但我们可以通过卷影复制实现。在提升特权的命令行中,使用 wmic 创建一个新的卷影并且指定来源磁盘,这样可以创建一个 C 盘的快照。我们可以用 vssadmin 命令来验证我们的操作。接着,我们可以从影拷贝中拷贝出 SAM 数据库 以及 SYSTEM 文件。之后用工具来解密 SAM 数据库。

wmic shadowcopy call create Volume='C:\'

image.png

列举当前的所有卷影拷贝:

vssadmin list shadows

image.png

可被复制与下载的 SAM SYSTEM 在如下位置:

\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\Config\SAM
\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\Config\SYSTEM

image.png

LSA 机密

LSA,即 Local Security Authority本地安全机构,是 Microsoft Windows 操作系统中安全子系统的核心组件。本地安全机构 (LSA) 负责管理系统的交互式登录、给用户分发安全访问令牌、实施本地安全策略等。 而LSA 机密是 Windows 中本地安全机构 (LSA) 使用的存储。

LSA 的目的是管理系统的本地安全策略,根据定义,这意味着它将存储有关用户登录、用户身份验证及其 LSA 机密等的私人数据。只有 SYSTEM 权限才可以访问 LSA 机密。LSA 机密所存储系统敏感数据有用户密码IE 密码服务帐号密码SQL 密码、系统账户密码计划任务中配置的帐号密码等。

提取 LSA 机密同样有多种方法,都类似于提取 SAM 中的凭证。

在线导出

目前大部分 C2 尚未集成导出 LSA 机密的命令或功能,但我们可以依旧使用 mimikatz 或者 Impacket 导出。导出 LSA 机密的命令为 lsadump::secrets

image.png

image.png

离线导出

LSA 机密被保存在注册表的 HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets 位置,而文件则位于 C:\Windows\System32\Config\SECURITY

注册表 Hive HKLM\SECURITY 中存储了明文密码、域缓存凭证、NTLM 哈希等形式的凭证。

reg save HKLM\SYSTEM C:\Windows\Tasks\SYSTEM
reg save HKLM\SECURITY C:\Windows\Tasks\SECURITY

image.png

LSASS 本地安全机构子系统服务

在上个小节讨论 LSA 机密的时候,提及了一下 LSA,即本地安全机构。在 Windows 上,有这么一个进程 lsass.exe,绝对是攻击者的首要攻击目标之一。虽然我们中的一些人知道可以从 lsass.exe 提取凭证,但 LSASS 本质上是什么呢,与 LSA 的联系又是什么呢?让我们先搞清楚这些。

名词与概念

本地安全机构 (LSA) 和本地安全机构子系统服务 (LSASS) 是 Windows 操作系统中处理安全和用户身份认证的密切相关组件。

本地安全机构

LSA 是 Windows 操作系统的一个组件,可执行安全策略并管理用户身份认证。它为各种安全支持提供程序 (SSP) 提供框架,这些提供程序处理特定的身份验证协议,例如 NTLM、Kerberos 等。LSA 负责根据 SSP 提供的身份验证数据生成访问令牌和管理用户会话。LSA 还维护 SAM 数据库。


本地安全机构子系统服务

LSASS 是一个 Windows 进程 (lsass.exe),实现了 LSA 概念并管理 SSP。它负责代表 LSA 执行安全策略和处理用户身份验证请求。LSASS 进程是 Windows 安全模型的重要组成部分,并以高权限运行,这使其成为寻求提取敏感信息(如密码或身份验证令牌)的攻击者的常见目标。

总之,LSA 是 Windows 中管理用户身份认证和执行安全策略的安全组件,而 LSASS 是实现 LSA 并运行 SSP 的进程。 两者相互关联,LSASS 进程负责 LSA 组件的功能。

认证包/安全支持提供程序 AP/SSP

AP/SSP 通过分析登陆数据来认证 Windows 用户,不同的 AP/SSP 对多种登陆过程以及认证协议提供支持。AP/SSP 以 DLL 形式存在,被 LSA 所加载和使用。常见的 AP/SSP 有 NTLM,Kerberos,WDigest,Credman 等。


从 lsass.exe 进程中导出凭证

正因为 LSASS 用于处理用户身份认证,因此在内存中保存了凭证,而当攻击者获得提升特权后,可以从中提取出明文或哈希形式的凭证。大家所知的 Mimikatz 中的 sekurlsa::logonpasswords 正是用于从 LSASS 内存中提取凭证的命令,该命令针对多种被 Windows 所使用的 AP/SSP,例如 Kerberos,MSV,WDigest。

Cobalt Strike 自带 mimikatz 的功能,考虑到 sekurlsa::logonpasswords 的使用频率很高,也有着 logonpasswords 短命令的形式,功能是一样的。我们能看到,以下截图中的用户 (包括主机账户) 的凭证可以来源于多个 SSP,甚至存在着明文形式的密码。

image.png

image.png

除了在线从 lsass.exe 中提取凭证,也可以将 lsass.exe 进程 (甚至整个内存) 导出成文件,让 mimikatz 等工具离线分析并提取凭证。导出的方式多种多样,使用系统内置方法的话,可以是任务管理员,导出 lsass.exe 进程。

image.png

Windows 的 system internal 中的 ProdDump

procdump64.exe -64 -accepteula -ma lsass.exe lsass.dmp

image.png

将导出的文件下载到自己主机,用 pypykatz (https://github.com/skelsec/pypykatz) 离线解析。

image.png

此外,BOF nanodump (https://github.com/fortra/nanodump) 可以在进程内导出 lsass,避免了工具落入文件系统,通过反射式加载在进程内执行导出行为。而且 nanodump 支持多种特性与参数,以增强 OPSEC,甚至绕过特定的安全控制。

克隆了该项目之后,导入 cna 脚本

image.png

根据 Gitub 中的案例,我们通过“克隆”进程以间接地打开 lsass.exe 的句柄并导出。

image.png

总之,如今实现导出 lsass.exe 进程的工具与方法很多,我们需要尽可能以更 OPSEC 的方式去达成。

PPL

随着凭证导出被攻击者的滥用,微软也开发出了相应的防御措施,例如 PPL。对于 IT 管理员,PPL 非常容易部署,是一个 quick-win。虽然 PPL 是可以被绕过的,但还是给导出凭证的操作增添了额外的难度。我们之前说过,Windows 有 4 种完整度等级,而 PPL,则是更高级的,这意味着即便是 SYSTEM 权限也无法访问被 PPL 保护的进程,而 lsass 支持 PPL保护。我们可以在注册表的如下位置添加 RunAsPPL 从而启用 PPL。

image.png

对于启用了 PPL 的主机 SRV01,无论是用 nanodump 还是 mimikatz 或其他类似工具,我们都无法正常导出 lsass 进程。nanodump 的报错告诉我们,无法获得对 lsass.exe 进程的句柄,即便我们已经是 SYSTEM 特权了。

image.png

image.png

PID 748 正是 lsass.exe

image.png


那么,我们可以怎么绕过 PPL 的限制呢?具备管理员权限后,我们当然可以删除 RunAsPPL 的注册表然后重启,但这样对于提取 lsass.exe 中的凭证也无意义可言了。既然 PPL 是驱动级的,那么我们自然可以通过加载签名的驱动来反制。但是,编写这样的驱动并为其签名,并不是一个门槛很低的选项。因此,我们可以去加载存在任意代码执行的脆弱驱动,例如 RTCore64.sys。该驱动存在 CVE-2019-16098 的漏洞,因为允许用户读写任意内存、IO端口等,因此会导致高特权下的代码执行,进而可被用于绕过微软的驱动签名 (默认情况下只允许加载签名的驱动) 策略部署恶意代码。

image.png

类似的驱动还有 PROCEXP152.SYS

image.png

因此,我们可以通过加载这些脆弱的且具有签名的驱动,实现内核级的代码执行而绕过 PPL。PPLControl (https://github.com/itm4n/PPLcontrol) 正是利用了脆弱的驱动从而实现 PPL 的绕过。我们需要得到 RTCore64.sys 这个驱动文件,以及编译后的 PPLcontrol.exe。

一并上传到 Srv01 上,加载驱动并运行:

sc.exe create RTCore64 type= kernel start= auto binPath= C:\windows\tasks\RTCore64.sys DisplayName= "control"
net start RTCore64

image.png

列举受保护的进程,我们发现本地安全机构也在其中。

image.png

记录下其 PID,然后将 PPL 保护给脱离。

image.png

这样,我们就能导出 lsass.exe 中的凭证了。

image.png

恢复 LSA 的 PPL 保护,这样我们再次不能从 lsass.exe 中导出凭证了。

image.png

实际上,我们甚至可以从用户态绕过 PPL。PPLDump (https://github.com/itm4n/PPLdump) 就是这么一个工具。它利用了一个技巧,使得系统创建一个新的任意的已知 DLL。PPL 并不检查已知 DLL 的数字签名,因此从而进行了 DLL 劫持攻击并在 PPL 中实现代码执行。该工具随着去年的一次更新补丁而失效,但遇到不那么新的系统是可以尝试的。PPLmedic (https://github.com/itm4n/PPLmedic) 也是一款在用户态就能绕过 PPL 的工具。nanodump 都集成了这 2 个工具的功能,因此我们并不需要单独去下载和编译 它们了。

image.png

在 Srv01 上,PPLdump 的方法成功了,而 PPLmedic 却失败了。

image.png

Credential Guard 凭据保护

Windows Defender Credential Guard 凭据保护 是一种虚拟化安全技术以防止 NTLM 哈希、Kerberos 票据、应用程序所存储的凭证的窃取进而组织。开启了凭据保护的主机,会分别有 Lsass.exe 进程以及 LsaIso.exe 进程。

凭据保护使用基于虚拟化的安全性 (VBS) 来隔离机密。VBS 利用硬件虚拟化功能创建一个安全的内存区域,该区域与普通操作系统分开。要了解攻击者在处理凭据保护时面临的挑战,可以参考在一个虚拟机内运行的正常操作系统和在另一个具有单独内核的虚拟机内运行的安全进程。这些 VM 由 Hypervisor 管理。

image.png

即使攻击者在操作系统中获得内核级的代码执行,他们仍然需要通过攻击 Hypervisor 或安全虚拟机来实现逃逸,这就是基于虚拟化技术的安全性相关的话题了。

小节开始说了,开启凭据保护的主机会有 2 个进程。LSAIso 进程将在安全虚拟机中运行,而 LSASS 和 LSAIso 可以通过高级本地过程调用 (ALPC) 进行通信。当 LSASS 进程想要保护一个秘密时,它可以调用 LSAIso 来加密它,然后将加密的秘密返回过来。理想情况下,只有 LSAIso 应该能够解密。一旦 NTLM 哈希受到保护,LSASS 进程仅持有一个隔离后的密文 (加密的 blob)。

image.png

如上图所示,LSAIso 进程具有 NTLM 支持。 当 LSASS 进程想要对加密的机密执行 NTLM 操作时,它可以调用 LSAIso 进程中的各种方法来执行操作。值得一提的是,LSAIso 没有网络访问权限。因此,即使 LSAIso 可以执行 NTLM 操作,LSASS 进程仍然负责执行操作前后的任何行为。例如,虽然 LSAIso 可以计算 NTLM 质询响应对,但 LSASS 负责接收和发送该对随机数。

对于开启了凭据保护的主机,使用 mimikatz 读取的凭证是这样的:

image.png

在 2020 年,有个很有意思的绕过技巧。 WDigest 模块,即 wdigest.dll,具有 2 个全局变量分别是 g_IsCredGuardEnabledg_fParameter_UseLogonCredential。这 2 个变量的名字就很直观,凭据保护是否启用,以及明文凭证是否应该存储在内存之中。通过将这两个变量的值进行修改,我们可以让 WDigest 误以为凭据保护未被启用,并且保存明文密码于内存之中。因此,在补丁 WDigest 之后的认证都会在内存中留下明文凭证。所以,我们需要做的是找到这 2 个变量的位置。我们可以在 https://gist.github.com/N4kedTurtle/8238f64d18932c7184faa2d0af2f1240 找到一个 PoC,但是变量的偏移是硬编码的。至于如何动态地找到变量偏移,属于更加高深的内容范围,不在此展开。

 

image.png

以上方法的局限是,之后新认证的用户的凭证可以提取了,但之前的还是无法捕获。而工具 PassTheChallenge (https://github.com/ly4k/PassTheChallenge) 通过利用 LSAIso 进程的功能以及加密后的 NTLM 哈希来还原出 NTLM 哈希。背后的密码学或算法原理较为复杂,不详细展开。

域缓存凭证

当域用户曾经登陆过域主机,便会将凭证缓存下来,以防联系不上域控制器的时候也能实现本地登陆。一个实际的情景可以是,某员工携带着笔记本出差。域缓存凭证不能直接地用于认证,但是可以将其离线破解,尝试还原出明文密码。

我们之前在使用 Impacket 导出 LSA 机密的时候,发现了下图所标注出来的域缓存凭证。实际上,这些缓存凭证存在于 HKLM\SECURITY 注册表 Hive。

image.png

我们还可以通过 Mimikatz 的命令 lsadump::cache 来提取。

image.png

但我们发现 mimikatz 提取出来的缓存凭证与 Impacket 提取出来的格式不同,我们需要手动将其转换成 $DCC2$<迭代数>#<用户名>#<哈希> 格式,然后再使用 hashcat 之类的工具离线破解。

DPAPI 数据保护应用接口

DPAPI,即数据保护应用接口,是一个提供加解密数据块的 Windows组件。它使用与指定用户或主机绑定的密码学密钥并且允许原生 Windows 功能以及第三方应用来透明地保护/解除保护给用户的数据。DPAPI 被 Windows 凭证管理器所使用于储存保存的秘密,凭证管理器数据块存放于用户的 AppData 文件夹中。

那么,DPAPI 保护哪些呢?例如:

Internet Explorer、Google Chrome 中的密码和表单自动填充数据
Outlook、Windows Mail、Windows Mail 等中的电子邮件帐户密码。
共享文件夹和资源访问密码
无线网络帐户密钥和密码
Windows CardSpace 和 Windows Vault 中的加密密钥
远程桌面连接密码,.NET Passport
凭据管理器中的网络密码
使用 API 函数 CryptProtectData 以编程方式保护的任何应用程序中的个人数据。 例如,在 Skype、Windows Rights Management Services、Windows Media、MSN messenger、Google Talk 等
...

我们可以使用原生工具 vaultcmd 来列举 AppData 中的数据块

image.png

或者使用 mimikatz 中的 vault::list 命令。

image.png

以及Seatbelt 中的 WindowsVault 模块 也可以枚举出:

image.png

如果前往控制面板 -> 凭据管理器,并且选择 Windows 凭据,我们会看到这些凭据是如何出现在用户面前的。而如果打开RDP,这些凭据会被自动填充。

image.png

image.png

加密后的凭证文件存在于 C:\Users\username\AppData\Local\Microsoft\Credentials 文件夹下。

image.png

我们也可以使用 Seatbelt 的 WindowsCredentialFiles 模块 来列举:

image.png

image.png

为了解密这些凭证文件,我们需要找到主加密密钥,即 MasterKey。上图的输出我们能看到 MasterKey 的 GUID。而 MasterKey 文件存储在 %APPDATA%\Microsoft\Protect\{SID} 目录下,其中 {SID} 是该用户的安全标识符,这些文件依旧是被加密的。

image.png

只有解密 MasterKey 获得实际的 AES256/128 密钥后,我们方能使用该密钥解密凭证文件。有以下两种方法来解密:

LSASS 注入

当有本地管理员权限的时候并且密钥缓存 (近期访问或解密过凭证) 在 LSASS 中,我们可以通过mimikatz 的 !sekurlsa::dpapi 命令读取 MasterKey,注意与 GUID 的一一对应。我们得到的 MasterKey 为 137c32458ea484baaa62214a46caec2b0a24d0f793275ac7cfc85cde5939a9ba084a1156c31cd262ae547c27be8d22f2dc34483dd0168957dc58438bc5750f9a

image.png

image.png

因为会与 LSASS 交互,所以会有 OPSEC 的风险。

MS-BKRP

MS-BKRP 是微软备份密钥远程协议,可用于向域控制器请求 MasterKey,不需要提升特权以及 LSASS 交互。这是为了以防用户修改或忘记密码,以及支持智能卡功能。

我们需要在目标用户的上下文中运行以下命令之一 (取决于是否知道明文密码)。

dpapi::masterkey /in:C:\users\<用户名>\AppData\Roaming\Microsoft\Protect\<用户SID>\<MasterKey GUID> /rpc
dpapi::masterkey /in:C:\users\<用户名>\AppData\Roaming\Microsoft\Protect\<用户SID>\<MasterKey GUID> /sid:<用户SID> /password:<密码> /protected

image.png

image.png

在获得主密钥之后,就可以进行最终的解密了,我们可以通过如下的 mimikatz 的命令进行解密。

 mimikatz dpapi::cred /in:C:\Users\<用户>\AppData\Local\Microsoft\Credentials\<凭证文件> /masterkey:<MasterKey>

 

image.png

我们之前发现 serveradm 的目录下有 3 个凭证文件,我们并不知道哪个平整文件是我们想要的,这没有关系,分别查看一下。

image.png

image.png

最终,我们获得了 serveradm 在 RDP 客户端中缓存的凭证,虽然 alice 的凭证我们已经之前知道了,但这是通过 DPAPI 得到的。此外,我们还知道了 Web02 上的 MSSQL sa 帐号的明文密码。

GPP 密码

注:本小节作为知识拓展,因为本 Lab 环境版本远高于 GPP 密码盛行的版本,因此尚未集成此内容。

为了阻止针对本地管理员密码的攻击,Windows曾经引入了 组策略偏好 Group Policy Preferences,即中心化管理本地管理员的密码。其具体做法是将加密后的密码XML 文件的形式保存在所有域主机都可访问的 SYSVOL目录下。

image.png

XML 文件中保存的密码经过了 AES-256 加密的,然而微软之前意外地将 AES 私钥放在了 MSDN 上 (https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be?redirectedfrom=MSDN)。因此,我们可以用 Get-GPPPassword 脚本来解密以获得明文密码。

image.png

image.png

在2014年,微软移除了该特性。尽管包含密码的 GPP文件不会再被创建,但我们依旧有可能找到过去遗留的文件并且从中获得明文密码。

NTDS.DIT

NTDS.DIT 文件是域控制器上存储 AD 数据的数据库,包含了域内对象的所有信息,例如用户,组,计算机,以及其他对象。更重要的是,该文件还存储域中所有用户的密码哈希,包括域管理员的。该文件位于 C:\Windows\NTDS\ntds.dit

image.png

在获得特定权限后,我们可以通过以下方式利用:

复制 NTDS.DIT 文件

在获得了域管理员之后,我们可以在域控制器上复制 NTDS.DIT 文件。但是类似于复制 SAM 数据库,因为 NTDS.DIT 在被实时使用,因此是被锁定的状态。我们依旧可以通过卷影拷贝技术来获得 NTDS.DIT文件。

image.png

下载 C:\Windows\System32\Config\SYSTEM 以及 C:\Windows\NTDS\ntds.dit

image.png

最后使用 Impacket 中的 secretdump 来离线解析

image.png

 

使用工具远程导出

有了域管理员的凭证后,我们可以使用诸如 impacket 之类的工具通过 RPC 协议远程导出 NTDS.DIT 中的哈希。

image.png

Windows 认证理论

我们在之前已经讨论了 NTLM 认证、Kerberos 认证、LSA 与 LSASS、SAM 等概念。在这小节,我们将对 Windows 认证理论做一个整合、归纳以及延伸。

本章节所使用的原理示意图和部分理论来自 https://attl4s.github.io/assets/pdf/Understanding_Windows_Lateral_Movements_2023.pdf 。 

Windows 认证类型与形式

发生在 Windows 环境中的认证过程,可以是本地认证,以及域认证。

本地认证

本地认证,例如是使用本地账户登陆主机。我们对于个人用的主机进行登陆往往就是本地登陆。本地用户只存在于特定系统,即只有该系统才知道有哪些本地用户,例如 SRV01\David。尽管系统与系统之间是互相独立的,但是不同的系统却可能有着相似甚至相同的帐号密码。例如 SRV01\DavidSRV02\David。我们之前知道了本地系统的信息存储于 SAM 之中,当用户以本地账户认证的时候,Windows 会根据 SAM 中的记录验证凭证。

image.png

域认证

域认证,例如是员工通过分发的域账户登陆工作站并访问内部资源。总之,域认证与本地认证是不同的机制。域用户和群组呈现在具体的 AD 域中,所有的域系统, (或在受信任的域中) 知道如何应对认证,它们会将认证的流程委派给域控制器。域用户和主机数据存储于 NTDS (NT 目录服务) 数据库中,当有用户尝试认证,域控制器则根据记录来验证凭证。

image.png

而认证的形式,可以笼统地分为物理认证以及远程认证。


物理认证

当用户在电脑面前,输入凭证并登陆,那么这是物理认证,适用于本地用户和域用户,只要目标系统知道认证的帐号。在 AD 中,默认情况下,任何域用户可以物理登陆任何域主机。但是,绝大多数情况下,我们没有机会在目标的环境中实现物理登陆。


远程认证

与物理认证有所不同的是,默认情况下需要特定权限才能进行远程登陆,例如属于本地管理员分组远程桌面用户分组。因此,我们应该关心的还是远程认证。

image.png

为了理解接下来的概念,我们需要对 Windows 认证机制很熟悉。


Windows 认证重要概念

认证包/安全支持提供程序 AP/SSP

虽然在前面的小节有讨论过了,让我们再回顾一下。AP/SSP 通过分析登陆数据来认证 Windows 用户,不同的 AP/SSP 对多种登陆过程以及认证协议提供支持。AP/SSP 以 DLL 形式存在,被 LSA 所加载和使用。常见的 AP/SSP 有 NTLM,Kerberos,WDigest,Credman 等。微软所提供的 AP 有 CSSPMicrosoft NegotiateMicrosoft NTLMMicrosoft KerberosMicrosoft Digest SSP,以及 Secure Channel

AP 提供了 Windows 充当客户端和认证服务器所需的逻辑。对于客户端,想要通过 Windows 认证连接到特定服务。对于服务器,想要让服务或应用程序支持 Windows 认证


SSP 接口

微软提供 SSP 接口以简单地将应用程序与认证系统无缝继承。


image.png

SSPI 的作用主要有这些:安全包管理凭证管理安全上下文管理消息支持


交互式登陆 vs 非交互式登陆

本地认证与域认证、物理认证与远程认证,这样的分类还不够。认证还有交互式非交互式之分。

交互式登陆,通常需要指定明文凭证,例如通过 Windows 的登陆页面进行认证。最重要的一点是用户凭证会缓存在 LSA 进程的内存中,为各个 AP 做准备。缓存的凭证还能让 Windows 给用户提供 SSO 体验。

image.png


image.png

而非交互式认证,应用程序代表用户使用缓存的凭证,也就是非交互式认证只应在交互式认证之后发生,也就是缓存凭证可用时。一些应用通过 SSPI 来实现这些认证。

image.png

image.png


登陆会话

登陆会话会在成功的认证之后创建,无论是物理认证、远程认证、域认证、本地认证、交互式登陆还是非交互式登陆。AP 缓存的凭证绑定在了登陆会话上。而在用户登出后结束。

当认证成功时,被选中的 AP 将执行这两个重要任务:创建一个新的登陆会话,以及向 LSA 提供认证用户的安全信息

image.png

LSA 使用该信息创建访问令牌来代表用户在系统中的的安全上下文

image.png

通常来说,登陆会话通常在交互式认证之后会有缓存的凭证,而非交互式的认证普遍会导致不缓存凭证的登陆会话。

登陆类型

在 Windows 中,所有的认证都应当作为以下登陆类型之一处理,无论是何种认证协议以及认证形式。

登陆类型 编号 认证形式 凭证是否存储于 LSA 中 案例
交互式 2 密码,智能卡,其他

物理登陆

runas

IIS 6 之前的基本认证

网络 3 密码,NT 哈希,Kerberos 票据 否 (除非委派被启用)

NET USER

RPC 调用

远程注册表

集成 Windows 认证的 IIS

SQL Windows 认证

批处理 4 存储于 LSA 机密中的密码 计划任务
服务 5 同上 Windows 服务
网络明文 8 密码

IIS 6 及之后的基本认证

带有 CredSSP 的 Windows PowerShell

新凭证 9 密码 runas /network
远程交互式 10 密码,智能卡,其他 远程桌面

导入 Get-LogonSession.ps1 脚本 (https://github.com/leechristensen/Random/blob/master/PowerShellScripts/Get-LogonSession.ps1)。查看 Web02 目前的会话列表 (大家自己操作得到的结果可能有所不同),仅筛选出 white-bird 域中的用户

get-logonsession | where-object {$_.Domain -eq 'WHITE-BIRD'}|select UserName, LogonType, AuthenticationPackage

image.png

因为 Web02 设置了 serveradm 的自动登陆,那么 serveradm 的交互式登陆自然是预期之中的。而 Web02 上同样运行着 SQL 服务,服务账号是 sql_service,因此服务登陆以及网络登陆同样是预期之中的。


令牌

当一个登陆会话被创建后,返回给 LSA 的信息被用于创建一个访问令牌。访问令牌是被保护的对象,它包含了一个认证用户的本地安全上下文。每个访问令牌被绑定给了一个登陆会话,访问令牌与进程或线程有关。

image.png

访问令牌包含了用户与其上下文的重要数据:用户 SID用户组归属特权列表会话 ID完整度等级令牌类型等。

image.png

image.png

在 Windows 中,相同的用户可以有着不同的上下文,例如 UAC 区分了中等和高完整度等级。这是因为 Windows 允许相同用户在同一个系统中有着不同的访问令牌和登陆会话。

image.png

Windows 使用访问令牌实施访问控制决定。Windows 对象有着访问控制列表,访问这样的对象的进程或线程有着访问令牌,而令牌信息被拿来与对象的 DACL 进行比较从而决定是否允许访问。

image.png

令牌的类型有主要令牌模仿令牌。主要令牌又被称为进程令牌,每个进程都有关联的主要令牌,当有新的进程被创建,默认是继承父进程的主要令牌

模仿令牌又被称为线程令牌,得以让一个线程运行在与父进程所不同的安全上下文中,通常用于客户端服务端的情景。当每个客户端连接到服务,新线程得以创建。正是因为模仿令牌,线程得以运行在不同客户端的上下文中,这使得服务可以通过 ACL 控制访问。

image.png

支持 Windows 认证的服务执行被称为客户端模仿的操作。当一个客户端连接到服务,客户端的凭证会被验证,以这个客户端为安全上下文的访问令牌被创建,服务在新的线程中置入令牌的备份,进而该线程可以代表这个客户端,并且受 ACL 的限制。因为一些服务只需要客户端的部分信息,即不需要完全的模仿。根据服务的配置,模仿令牌可以有着不同的模仿等级:

SecurityAnonymous:服务器不能模仿客户端的身份

SecurityIdentification:服务器可以获得客户端的身份和特权但不能模仿

SecurityImpersonation:服务器可以在本地主机上模仿用户的安全上下文

SecurityDelegation:服务器可以在远程主机上模仿用户的安全上下文


用户模仿

用户模仿即创建劫持另一个用户的安全上下文以在网络中代表这个用户。创建一个安全上下文通常需要凭证,而劫持一个安全上下文则需要特权。用户模仿可以通过这些途径实现:令牌操纵密码NT 哈希Kerberos 票据等。

image.png

请回顾跟登陆会话绑定的凭证,通常是交互式认证的产物。如果想通过使用一个令牌来访问网络资源,这个令牌必须与一个有着凭证的会话相关联。

image.png

Windows API 提供了能用于操纵令牌的功能,例如复制令牌。但是,我们需要特权:本地管理员或者 SYSTEM服务账号 (土豆家族)。而低权限用户只能操纵自己的令牌。

DuplicateTokenEx API 可用于创建一个复制现有令牌的新访问令牌。

BOOL DuplicateTokenEx(
  [in]           HANDLE                       hExistingToken,
  [in]           DWORD                        dwDesiredAccess,
  [in, optional] LPSECURITY_ATTRIBUTES        lpTokenAttributes,
  [in]           SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  [in]           TOKEN_TYPE                   TokenType,
  [out]          PHANDLE                      phNewToken
);

如果是劫持一个已有令牌的方法,有着令牌模仿进程注入的方法。前者复制目标的令牌并且将其用于已有进程或者新进程,后者将载荷注入到目标令牌所寄居的进程

image.png

SharpToken (https://github.com/BeichenDream/SharpToken) 是一款可以通过操纵令牌来实现用户模仿的工具,在 本地管理员或者 SYSTEM 权限下,我们可以列举所有可用令牌,并窃取想要的令牌。

image.png

Cobalt Strike 中的内置命令 steal_token 也可实现令牌窃取

image.png

而通过进程注入实现令牌劫持的流程图如下:

image.png


有明文密码!

runas.exe

Windows 原生程序 runas.exe 可以通过提供额外的凭证来创建进程,例如用户想以另一个账户的身份运行特定进程。runas.exe 默认 (不提供其他选项) 会通过 LSA 验证提供的凭证的正确与否,类似于交互式认证。

image.png

对本地账户以及域账户都成立。

image.png

如果没有提供正确的凭证,则会失败。

image.png

在 Cobalt Strike 中,runas 命令则是对 Windows 系统中 runas.exe 的实现。

image.png

C# 工具 runascs (https://github.com/antonioCoco/RunasCs) 也有着相似的功能和实现,并且自定义程度更高,用户可以指定登陆类型。例如,指定 -l2,则是交互式认证。

image.png

在使用 runas.exe 以 white-bird\condrey 身份创建的 cmd.exe 进程以及使用 runascs.exe 以 wanh 身份创建 cmd.exe 进程后,我们可以用之前的脚本命令发现新增了用户的登陆会话。

image.png


runas.exe /netonly

runas.exe 程序有着 /netonly 的选项,它告诉 runas.exe 这个指定的凭证仅用于远程访问,而 LSA 并不会验证凭证的正确与否,也就是即便输入错误的凭证也不会有报错信息。

image.png

指定了 /netonly 选项后,假设提供的凭证是有效的,那么新的进程在本地层面保持原来的身份,但在网络层面却是新的身份,即有着 2 个不同的安全上下文prod\john 对于 Srv01 具有 WinRM 访问。通过 /netonly 创建的新 powershell.exe 进程中,我们发现身份还是 prod\alice,但如果使用 john 的访问在 Srv01 上远程执行命令,身份则是 john 了。

image.png

runas.exe 的实现使用的是 CreateProcessWithLogonW API,即以提供的凭证的安全上下文创建新的进程。/netonly 选项使用了 LOGON_NETCREDENTIALS_ONLY 登陆选项,创建和使用新的登陆会话,但是令牌还是原来的

BOOL CreateProcessWithLogonW(
  [in]                LPCWSTR               lpUsername,
  [in, optional]      LPCWSTR               lpDomain,
  [in]                LPCWSTR               lpPassword,
  [in]                DWORD                 dwLogonFlags,
  [in, optional]      LPCWSTR               lpApplicationName,
  [in, out, optional] LPWSTR                lpCommandLine,
  [in]                DWORD                 dwCreationFlags,
  [in, optional]      LPVOID                lpEnvironment,
  [in, optional]      LPCWSTR               lpCurrentDirectory,
  [in]                LPSTARTUPINFOW        lpStartupInfo,
  [out]               LPPROCESS_INFORMATION lpProcessInformation
);


make_token

多个 C2 工具中都有着类似于 make_token 功能的命令,Cobalt Strike 自然也是有这样的功能和命令的。make_token 允许我们在知道其他用户明文密码的情况下模仿他们,调用的是 LogonUserA API。

BOOL LogonUserA(
  [in]           LPCSTR  lpszUsername,
  [in, optional] LPCSTR  lpszDomain,
  [in, optional] LPCSTR  lpszPassword,
  [in]           DWORD   dwLogonType,
  [in]           DWORD   dwLogonProvider,
  [out]          PHANDLE phToken
);

LogonUserA 相比 CreateProcessWithLogon 更好的地方在于,我们可以在不创建新的进程的情况下创建新的登陆会话/令牌对,并且可以指定不同的登陆类型 (在调用 LogonUserA 获得令牌后,可以创建新的进程)。Cobalt Strike 中的 make_token 使用的是 LOGON32_LOGON_NEW_CREDENTIALS 登陆类型,与 runas.exe /netonly 一致、

image.png

调用该 API 得到的令牌可以被传递给 ImpersonateLoggedOnUser API,这允许调用的线程模仿令牌的上下文 (被模样的用户的上下文)。

BOOL ImpersonateLoggedOnUser(
  [in] HANDLE hToken
);

当不需要模仿的时候,使用 rev2self 命令退出。

BOOL RevertToSelf();

总之,在高完整度下,操纵令牌是容易的,我们可以做这些事情:窃取系统内的任何令牌注入到任何进程将窃取的令牌应用于当前的上下文用窃取的凭证创建新的进程。如果是低完整度下,我们不能使用令牌创建新的进程 (CreateProcessAsUser CreateProcessWithToken API 需要管理员特权),因此考虑内联执行,例如 BOF。


有 NT 哈希!

如果我们没有明文密码,只有 NTLM 哈希呢?如何实现用户模仿?可惜的是,Windows 没有这样的认证功能,没有 LogonUserWithHash 或者 CreateProcessWithHash API。如果我们想通过 LSA 来利用哈希,我们需要与 LSASS 进程打交道。LSASS 存储着所有登陆会话以及缓存凭证,需要高权限,而且还很有风险。

但我们其实也不必依赖于 LSA,这不局限于有 NTLM 哈希,包括有明文密码或者其他类型的凭证。我们可以使用对 NTLM 或者 Kerberos 有原生支持的工具。

与 LSA 交互

Mimikatz 可以用来完成基于 LSA 的哈希传递。换句话说,哈希传递也可以不必依赖于 LSA。Mimikatz 可以使用 NTLM 哈希而非明文密码来创建进程,通过向 lsass 进程注入数据实现。因为需要修改 lsass 进程,自然需要高权限。

Web02 上,任何目前可用的令牌都不足以访问 Dc05

image.png

在 SYSTEM 权限下,使用 mimikatz 的 PTH 命令

image.png

我们可以看到现在 lsass.exe 进程是 RW 权限了。这个命令将新凭证通过命名管道传递,然后 Beacon 再模仿它。

Mimikatz 的 PTH 相当于提供哈希而非明文密码版本的 runas.exe /netonly。先通过 CreateProcessWithLogon API 创建新的进程,其中使用的是 LOGON_NETCREDENTIALS_ONLY 登陆选项。然后,识别出新创建的登陆会话,将凭证内容填充到目标的登陆会话中。

image.png

现在,我们可以访问 Dc05 了。

image.png

用图来显示普通认证流程以及 Mimikatz 的 PTH 的话,如下所示:

image.png

image.png


不与 LSA 交互

不与 LSA 交互的 PTH 则就简单多了,只需要找到原生支持我们想要使用的协议的工具即可,例如 Impacket,CrackMapExec 等,而不需要与复杂的 Windows 组件打交道。

如果是 NTLM 协议:

image.png

如果是 Kerberos 协议,我们可以使用 Rubeus 或者 Impacket,这类工具可以产生获得 TGT/TGS 的 Kerberos 原始流量。至于如何利用得到的票据,我们下文就说。

image.png


有 Kerberos 票据!

虽然 Windows 没有基于 NTLM 哈希的认证功能,但对于 Kerberos 票据是有的。我们同样可以选择与 LSASS 交互,或者不与 LSASS 交互。

与 LSA 交互

我们可以将票据导入到存在的登陆会话中。将票据导入到当前的会话中不需要特权,而导入到其他会话中则需要特权。

假如我们已经得到或伪造了其他用户的 Kerberos 票据,并且打算使用它们。PTK,即票据传递是将这样的票据导入到攻击者所控制的登陆会话的技术,这使得我们可以在网络中模仿受害者。如果导入了一张 TGT 到现有会话中,那么原来的会被覆盖。

image.png

Rubeus 的 PTT 命令正是这样的原理

image.png

Cobalt Strike 的命令 kerberos_ticket_use 具有同样作用。

image.png

这项技术的实现,是使用了 LsaCallAuthenticationPackege API。这个 API 使得应用程序可以与 Windows AP 进行对话

NTSTATUS LsaCallAuthenticationPackage(
  [in]  HANDLE    LsaHandle,
  [in]  ULONG     AuthenticationPackage,
  [in]  PVOID     ProtocolSubmitBuffer,
  [in]  ULONG     SubmitBufferLength,
  [out] PVOID     *ProtocolReturnBuffer,
  [out] PULONG    ReturnBufferLength,
  [out] PNTSTATUS ProtocolStatus
);

总之,如果使用与 LSA 交互的方法导入票据,我们可以在低权限的情况下将票据导入到当前会话。可以是使用 make_token 创建并模仿一个新的登陆会话,导入票据以防止覆盖原有的 TGT。在 alice 会话的 file01 Beacon 中,我们使用 make_token 命令创建并模仿一个新的登陆会话,密码不需要是有效的。此时,这个新登陆会话的还不存在任何票据,我们使用 kerberos_ticket_use 导入 white-bird\administrator 的票据,发现可以访问 Dc05 了。如果使用 rev2self 退出模仿,便不能访问了。

image.png

image.png

或者在高权限的情况下,先创建一个牺牲进程用来导入票据,因为一个登陆会话每次只能持有 1 张 TGT,在当前会话导入 TGT 可能导致认证紊乱。将票据导入到该牺牲会话之后,窃取令牌或者在该进程注入载荷

目前,我们在 Web02 上不能访问 Dc05 (清除了现有票据以避免干扰)。使用 createnetonly 命令创建一个新的隐藏进程,我们可以看到新的会话 ID 以及进程 ID。但目前这个会话里还没有 TGT。我们还指定了域名帐号密码(不会被验证),这是为了在日志中看起来更加清白,毕竟 Rubeus 随机生成的这些数据会成为嫌疑。

image.png

因此,我们导入 Administrator 的 TGT,指定目标 LUID

image.png

窃取令牌后,方可访问了。

image.png


不与 LSA 交互

我们可以用 Impacket 之类的工具来使用得到的票据。我们可以使用 Impacket 中的 ticketConverter 将票据在 kirbi 格式与 ccache 格式直接互相转换。在 Linux 端,所接受的格式是 ccache,我们需要设置 KRB5CCNAME 环境变量指向该 ccache 票据。

image.png

哈希传递 Pass The Hash

Pass The Hash,即哈希传递,是一种可以让我们使用 NTLM 哈希对 Windows 服务进行认证,而无需明文密码的技术。在上一个小节,我们讨论了如果只有 NTLM 哈希,要实现用户模仿该怎么做的时候有提到 PTH,在这一小节我们继续延伸和补充一下。

我们之前讲过 NTLM 认证的步骤,让我们再来回顾一下:

image.png

哈希传递认证可以跳过上图中的第一步,通过使用例如 Mimikatz 之类的工具实现。需要注意的是,哈希传递攻击仅可以用于 NTLM 认证,而非 Kerberos 认证。一些安全工具,例如 Impacket, 不仅可以通过 PTH 认证,而且还可以实现代码执行,而这之后的原理则是攻击者通过 SMB 协议使用 NTLM 哈希连接目标服务器。大部分工具通过 Service Control Manager API 开启一个新的 Windows 服务并且通过命名管道来通信。这项技术需要与目标 SMB 服务的连通,并且可以访问目标主机的 ADMIN$ (在 ADMIN$ 中写入一个服务二进制文件),这意味着需要本地管理员权限。接下来,我们来看看常见的 PTH 用法。


接触 LSASS

Mimikatz 的 PTH

我们可以通过以下命令创建一个新的牺牲会话,并用我们提供的帐号NTLM 哈希域信息来替换占位符信息。

image.png

image.png

该方法需要本地管理员特权,并且该操作会与 LSASS 交互,而且如果 PPL 启用的话,也会失败。

 sekurlsa::pth /user:<用户名> /domain:<域> /ntlm:<ntlm> 

执行该命令需要本地管理员特权,但被认证的用户不需要有本地管理员权限。

image.png


不接触 LSASS

Impacket 之 psexec

如上文所说,psexec不仅可以通过 PTH 认证,还能实现远程代码执行。原理则是通过 SMB 服务进行认证,在目标的 ADMIN$ 上传服务二进制文件,再通过 SCM 创建新的服务并获得 shell。需要目标用户对目标主机具有本地管理员特权。

image.png

在 psexec 的日志信息中,我们可以窥探到中间的过程。


Impacket 之 mssqlclient

Impacket 不仅可以协助我们通过 PTH 认证获得远程代码执行,但是我们也可用于访问特定服务,例如 MSSQL。

image.png


Impacket 之 secretdump

除此之外,PTH 还可以通过 Impacket 来远程导出目标主机的凭证,包含 SAM 数据库、域缓存凭证、DPAPI、LSA 机密等内容。原理为在认证之后通过操纵远程注册表来进行凭证导出操作,需要认证用户具有本地管理员权限。

image.png


CrackMapExec 中各项功能

除了 Impacket 外,我们之前提到过 CME (https://github.com/Porchetta-Industries/CrackMapExec) 也是一款内网渗透瑞士军刀,其功能越发丰富和完整。CME 可以用于 AD 枚举与利用、密码喷洒、权限确认 (例如该用户对目标主机是否具有 WinRM 访问权)、代码执行等。

image.png


xfreerdp 的 PTH 认证

我们甚至可以通过 PTH 来访问远程主机的 RDP 服务,这里我们需要用到工具 xfreerdp。

xfreerdp /v:<IP> /u:<用户名> /d:<域名 FQDB> /pth:<哈希> /dynamic-resolution 

image.png

然而,我们会得到这样的报错:

image.png

因此,我们需要开启受限管理模式。受限管理模式,即 Restricted Admin,可以防止用户通过 RDP 访问目标主机后,在目标主机上留下凭证 (NTLM哈希)。在受限管理模式下,用户使用的是网络认证而非交互式认证。我们可以通过以下 Powershell 命令取消禁用受限管理模式 (即开启)。

New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name DisableRestrictedAdmin -Value 0

 image.png

然后,我们就可以通过 xfreerfp 使用 PTH 访问 RDP 服务了。

image.png

当然,因为在受限管理模式下,RDP 是通过网络认证访问,我们也可以在 Mimikatz 中 直接进行 PTH 认证后通过网络认证访问 RDP 服务。

sekurlsa::pth /user:<用户> /domain:<域 FQDN> /ntlm:<NTLM 哈希> /run:"mstsc.exe /restrictedadmin"

image.png

密钥传递 Overpass The Hash / Pass The Key

Overpass The Hash,又称为 Pass The Key密钥传递,是 PTH 的一种延伸,我们通常在 NTLM 认证被禁用、只有 Kerberos 认证可用的情况下使用。相比与 PTH 直接用 NTLM 哈希进行认证,OTH 认证通过目标用户的 NTLM 哈希 或者 AES 密钥申请对应的 TGT 或者 TGS,从而访问相应的主机或者服务。

AES 密钥是什么呢?我们在 mimikatz 终端里执行命令 sekurlsa::ekeys,我们可以提取出 AES 密钥。

image.png

在申请 TGT的时候,我们可以使用工具 Rubeus 来帮助我们实现

Rubeus.exe asktgt /user:<用户名> /domain:<域名fqdn> /aes256:<aes 密钥> /nowrap

image.png

需要注意的是,从技术上来说,/aes256 也可以替换成 /rc4,即 NTLM 哈希。但是,请求 TGT 会产生 4768 事件,并且我们会看到 密钥类型是RC4-HMAC (0x17),但是如今 Windows 系统中的默认密钥类型是 AES256 (0X12)。因此,我们依旧选用 AES256,可以使我们的活动被正常操作所淹没。

票据传递 Pass The Ticket

票据传递技术类似于密钥传递技术,只不过相比使用密钥,用的是票据。在讲解 PTT 之前,我们先来了解一下在 Windows 与 Linux 平台上有关域凭证的文件,它们可以通过工具实现互相转换。

kirbi

我们通过 Mimikatz 或者 rubeus 请求与导出的 TGT 或者 TGS票据格式为 kirbi。对于 Mimikatz,我们可以使用命令 sekurlsa::ticket /export 导出所有票据,格式为 kirbi。

image.png

image.png

 如果使用 Rubeus,可以使用 rubeus.exe dump 命令导出目前所有票据。

image.png

image.png

当然,我们可以指定导出哪些票据。先通过 rubeus.exe triage 命令查看当前所有的登陆会话以及对应的票据,再通过 /luid 参数指定要导出票据的登陆会话。

rubeus.exe triage
rubeus.exe dump /luid:<登陆会话 ID> /nowrap

image.png

image.png

至于将文本保存为 kirbi 文件,在Windows端,我们可以通过如下的 Powershell 命令保存 kirbi 文件。在 Linux 端,我们可以通过命令 echo '<ticket>' | base64 -d > example.kirbi 实现。

[System.IO.File]::WriteAllBytes("<目标地址>", [System.Convert]::FromBase64String("<票据>"))

image.png

image.png

ccache

在 Linux端,如果 Linux 主机上有活跃的会话,那么在 /tmp 目录下会产生该用户的凭证缓存文件,Credential Cache,即 ccache 文件,格式为 krb5cc_xxx,例如krb5cc_1394201122_MerMmG。ccache 文件中保存了该用户的票据信息,例如 TGT,TGS 等。在 Linux 域主机上,环境变量 KRB5CCNAME 指向了票据的地址,以获得域用户的上下文。我们也可以通过命令 export KRB5CCNAME=<ccache 文件地址> 来手动更改环境变量。

image.png

image.png

我们可以通过 Impacket 的 ticketConverter 脚本将票据在 ccachekirbi 形式中互相转换。

image.png

image.png

ccache 文件仅对应域用户以及 root 用户可读。如果作为活跃用户,我们可以通过 kinit 申请新的 TGT,以及通过 kvno [SPN] 申请新的 TGS。


keytab

keytab 文件包含 Kerberos 主体名称凭证,例如NTLM哈希。我们在之前提到过可以使用脚本 (https://github.com/sosdave/KeyTabExtract) 从中提取 NTLM 或者 AES256 凭证,那么在此基础上我们想要获得其他格式的票据自然不是难事。每台 Linux 域计算机的 /etc/krb5.keytab 文件是其 keytab 文件,默认情况下可由 root 访问。

类似于 PTH,一些工具例如 Impacket 支持直接使用 keytab 进行认证。

image.png


好了,在了解了以上几种凭证文件类型后,我们来讨论如何利用及导入票据。


Windows 端票据传递

在 Windows 端,我们主要可以使用 Mimikatz 以及 Rubeus 等工具来导入票据。Cobalt Strike 则支持 kerberos_ticket_usekerberos_ccache_use 命令来实现。

在 CobaltStrike 中通过 make_token 命令生成一个牺牲会话,然后导入要传递的票据。至于创建一个牺牲会话后再导入凭证,原因在 Windows 认证原理小节中有提过,新导入的 TGT 会替换原有的,可能导致认证紊乱,而新创建的牺牲会话中尚无 TGT。

然后,我们能在其他主机上以 white-bird\serveradm 身份顺利访问 Web02 的 C$

image.png

Linux 端票据传递

而在 Linux 端传递票据的话,我们先需要将 kirbi 文件转换为 ccache 格式,然后设置 KRB5CCNAME 环境变量,之后就可以使用票据认证了。

image.png

LAPS 本地管理员密码解决方案

为了进一步保护本地管理员的凭证,本地管理员密码解决方案 (LAPS) 是一种用于管理域主机上的本地管理员凭证的解决方案。 本地管理员帐户可以是默认帐户自定义帐户。部署 LAPS 后,密码是随机的、自动更改的,并且与其他帐户的密码不同。在域计算机上安装 LAPS 后,计算机会多出两个属性 ms-mcs-AdmPwnExpirationTime ms-msc-AdmPwd,分别是过期时间明文密码。 LAPS 通过域中的 GPO LAPS 进行管理。 域管理员对 ms-msc-AdmPwd 属性具有读取权限,但可以将读取权限委派给其他主体,如特定域用户或组。从系统管理员的角度,我们可以在 DC 上查看最新的LAPS密码。

image.png

image.png

枚举

在 RAVEN-MED 域中,LAPS 有为一些域主机 (其实也就 1 台 域主机) 安装。我们导入 powerview 脚本,执行以下命令:

Get-NetComputer -Filter "(ms-mcs-admpwdexpirationtime=*)" | select dnshostname

我们看到,RAVEN-MED 域中只有 mon01 被配置了 LAPS。

image.png

根据 Bloodhound,我们发现 PROD 域中的 harold 可以阅读 mon01 的 LAPS 密码。

image.png


读取明文密码

在确定了 prod\harold 可以阅读 mon01 的 LAPS 密码后,我们需要获得 harold 的上下文。根据之前的利用,我们可以很轻松地得到 harold 的凭证从而获得访问。

然后执行以下命令以读取明文密码:

Get-NetComputer -Filter "(ms-mcs-admpwd=*)" | Select dnshostname,ms-mcs-admpwd

image.png

新 LAPS 

就在 2023 年 4 月,微软发布了新一代 LAPS,而我们目前为止所讲的 LAPS 成为旧版本的了。新的 LAPS 有以下特征

1:Windows 原生集成。

2:支持 Azure AD

3:对本地 AD 的 LAPS 增加新的特性,例如下图所示

image.png

gMSA 组托管服务账号

注:本小节作为知识拓展,本 Lab 尚未集成此内容。

gMSA,即组托管服务帐号,提供了对分布在多台服务器上的服务帐号的自动化的密码管理SPN管理、以及委派管理权。使用 gMSA 有助于防御 Kerberoast 攻击。包含密码信息的 blob 被存储在 gMSA 的属性 msds-ManagedPassword 中。只有特定的主体可以读取密码 blob,默认情况下即便是域管理员也无法读取。

因为 gMSA 具有 msDs-GroupManagedServiceAccount 的对象类,因此我们可以轻松找到。

image.png

在找到了可以读取 gMSA 的主体之后,我们可以在其上下文中使用工具 GMSAPasswordReader (https://github.com/rvazarkar/GMSAPasswordReader) 获取 NTLM 哈希,之后从而破解哈希或者 进行 PTH 认证。

image.png

第9章课后作业

练习

1:导出任意一主机的 SAM 数据库,分别采用在线和离线方法

2:导出任意一主机的 LSA 机密,分别采用在线和离线方法

3:导出任意一主机 (除了 Srv01) 的 LSASS 内存中的凭证,分别采用在线和离线方法

4:复现 PPL 绕过的方法

5:mimikatz 的驱动 mimidrv.sys 也可用于绕过 PPL,请尝试一下

6:在多台靶机上枚举域凭证 (应该能发现不少),看看哪些能被字典攻击所还原出明文?

7:除了教材中举例的 Web02,我们还能在其他主机上从 DPAPI 中得到哪些明文凭证?

8:导出任意一域控制器的 NTDS 数据库,分别采用在线和离线方法

9:理解 Windows 认证理论小节中的理论知识

10:哪个 API 可以实现令牌复制?

11:尝试使用进程注入的方法来模仿用户

12:目前我们有用户的哈希,可以使用 Impacket 进行不接触 LSA 方式的 PTH。有一些 Powershell 脚本也可以达到这样的目的,请尝试

13:为什么 make_token 比 runas 更好呢?

14:除了明文密码、哈希、票据,还可以直接或间接地使用哪些类型的“凭证”可以让我们实现用户模仿?

15:探究 CreateProcessAsUserCreateProcessWithTokenCreateProcessWithLogon, 和 LogonUser 这些 API 直接的区别与联系

16:探究登陆会话令牌进程三者之间的关系。

17:导入票据的时候,我们为什么最好要创建牺牲会话或牺牲进程呢?

18:对域内任意一台其他主机开启受限管理模式,并使用 PTH 认证

19:为什么 Mimikatz 实现的 PTH 需要接触 LSASS,而 Impacket 实现的并不需要呢?

20:Impacket 支持使用 keytab 认证,请在 Web01 上创建一个用户的 keytab,再用其 keytab 文件认证到目标主机 (受害者具有特权的主机)。

面试专题