利用SeTrustedCredmanAccessPrivilege转储存储凭据
我一直在研究Windows的各种令牌特权,试图找出它们的用途。其中一个看起来有趣的是SeTrustedCredmanAccessPrivilege
,其文档描述为“以受信任调用者身份访问凭据管理器”。凭据管理器允许用户将凭据(如Web或域账户)存储在只有他们自己能访问的中央位置。它使用DPAPI进行保护,因此理论上只有在用户已通过系统身份验证时才能访问。问题是,拥有SeTrustedCredmanAccessPrivilege
会授予什么权限?我立即找不到有人费心记录它,所以我想我得自己来。
凭据管理器是那些在设计阶段可能听起来很棒的功能之一,但确实会引入安全风险,特别是如果它用于存储特权域凭据,例如用于远程桌面访问。应用程序(如远程桌面客户端)可以使用CredWrite
API并在CREDENTIAL
结构中指定用户名和密码来存储域凭据。凭据类型应设置为CRED_TYPE_DOMAIN_PASSWORD
。
然后,应用程序可以使用CredRead
或CredEnumerate
等API访问当前用户的存储凭据。但是,如果凭据类型是CRED_TYPE_DOMAIN_PASSWORD
,包含密码的CredentialBlob
字段始终为空。这是由实现凭据管理器RPC服务的LSASS施加的人为限制。如果正在读取域凭据类型,则永远不会返回密码。
如果无法读取密码,域凭据如何被使用?在LSASS进程中运行的安全包(如NTLM/Kerberos/TSSSP)可以使用不限制读取域密码的内部API。因此,当您向远程桌面服务进行身份验证时,将使用目标名称查找可用凭据,如果存在,用户将自动进行身份验证。
凭据以用户的DPAPI密钥加密存储在用户配置文件中的文件中。为什么我们不能直接解密文件来获取密码?在写入文件时,LSASS在加密的blob中设置了一个系统标志,这使得DPAPI拒绝解密blob,即使它仍然在用户的密钥下。只有在LSASS中运行的代码才能调用DPAPI来解密blob。
如果我们拥有管理员权限,获取密码就变得微不足道。阅读Mimikatz wiki页面以了解可以使用该工具访问凭据的各种方式。然而,这归结为以下方法之一:
- 修补LSASS中的检查,使其在从普通用户读取时不空白密码。
- 将代码注入LSASS以解密文件或读取凭据。
- 直接从LSASS的内存中读取它们。
- 在了解用户密码的情况下重新实现DPAPI以忽略系统标志。
- 使用域密钥备份协议玩游戏。
例如,Nirsoft的CredentialsFileView似乎使用注入LSASS技术来解密受DPAPI保护的凭据文件。(注意:我只查看了v1.07,因为v1.10似乎不再可供下载,所以可能现在不同了。更新:它似乎再次可供下载,但Defender认为它是恶意软件,情况依旧)。
此时,您可能猜到SeTrustedCredmanAccessPrivilege
允许调用者访问用户的凭据。但具体如何?查看包含凭据管理器实现的LSASRV.DLL,该特权在函数CredpIsRpcClientTrusted
中检查。这仅由两个API调用:CredrReadByTokenHandle
和CredrBackupCredentials
,它们通过CredReadByTokenHandle
和CredBackupCredentials
API导出。
CredReadByTokenHandle
API并不那么有趣,它基本上是CredRead
,但允许通过提供用户的令牌来指定要读取的用户。据我所知,读取域凭据仍然返回空密码。另一方面,CredBackupCredentials
很有趣。它是CREDWIZ.EXE用于备份用户凭据的API,可以在以后恢复。此备份包括所有凭据,包括域凭据。该API的原型如下:
|
|
备份过程稍微复杂,首先您在桌面上运行CREDWIZ,选择备份并指定要写入备份的文件。当您继续备份时,该进程会向您的WinLogon进程进行RPC调用,带有凭据路径,该路径在安全桌面上生成一个新的CREDWIZ副本。此时,您被指示使用CTRL+ALT+DEL切换到安全桌面。在这里,您输入密码,该密码用于加密文件以保护静态数据,并在凭据恢复时需要。CREDWIZ甚至会确保它满足您系统的密码复杂性策略,多么慷慨。
CREDWIZ首先将文件存储到临时文件,因为LSASS使用系统DPAPI密钥加密加密的内容。然后可以解密文件并写入最终目的地,并进行适当的模拟等。
调用此API的唯一要求是启用SeTrustedCredmanAccessPrivilege
特权。假设我们是管理员,获得此特权很容易,因为我们可以从另一个进程借用令牌。例如,检查哪些进程拥有该特权显示显然是WinLogon,还有LSASS本身,尽管它可能不需要它。
|
|
我真的不知道ATIECLXX.EXE进程用SeTrustedCredmanAccessPrivilege
做什么,最好不要问 ;-)
要使用此API作为管理员备份用户的凭据,请执行以下操作:
- 打开一个WinLogon进程以进行PROCESS_QUERY_LIMITED_INFORMATION访问,并获取其令牌的句柄,具有TOKEN_DUPLICATE访问权限。
- 将令牌复制到模拟令牌中,然后启用
SeTrustedCredmanAccessPrivilege
。 - 打开目标用户的令牌,该用户必须已经通过身份验证。
- 在模拟WinLogon令牌时调用
CredBackupCredentials
,传递要写入的路径和NULL密码以禁用用户加密(只是为了简化操作)。是CREDWIZ强制执行密码策略,而不是API。 - 在仍然模拟时打开文件并使用
CryptUnprotectData
API解密它,将解密的数据写回。
如果一切顺利,您将拥有所有用户凭据的打包二进制格式。我立即找不到有人记录它,但人们显然以前做过。我将把所有这些留给读者作为练习。我不想提供实现。
当已经存在许多其他选项时,为什么要这样做?主要优势(如果可以称之为优势的话)是您从不接触LSASS,也绝对不向其中注入任何代码。如果LSASS作为PPL运行,这无论如何都是不可能的。您也不需要访问SECURITY hive来提取DPAPI凭据或知道用户的密码(当然,假设他们已经通过身份验证)。关于唯一稍微可疑的事情是打开WinLogon以获取令牌,尽管可能有替代方法来获取合适的令牌。