利用SeTrustedCredmanAccessPrivilege转储存储凭据
我一直在研究Windows中的各种令牌权限,试图找出它们的用途。其中一个看起来有趣的是SeTrustedCredmanAccessPrivilege,文档中描述为“以受信任调用者身份访问凭据管理器”。凭据管理器允许用户存储凭据,例如Web或域账户,存放在只有他们能访问的中心位置。它使用DPAPI保护,因此理论上只有在用户已认证到系统时才能访问。问题是,拥有SeTrustedCredmanAccessPrivilege会授予什么?我找不到有人费心记录它,所以我想我得自己来。
凭据管理器是那些在设计阶段听起来很棒的功能之一,但确实引入了安全风险,特别是如果它用于存储特权域凭据,例如用于远程桌面访问。应用程序,如远程桌面客户端,可以使用CredWrite API并通过CREDENTIAL结构指定用户名和密码来存储域凭据。凭据类型应设置为CRED_TYPE_DOMAIN_PASSWORD。
然后,应用程序可以使用CredRead或CredEnumerate等API访问当前用户的存储凭据。然而,如果凭据类型是CRED_TYPE_DOMAIN_PASSWORD,包含密码的CredentialBlob字段始终为空。这是由LSASS实施的一个人为限制,它实现了凭据管理器RPC服务。如果正在读取域凭据类型,它将永远不会返回密码。
如果你无法读取密码,域凭据如何被使用?在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认为它是恶意软件, plus ça change)。
在这一点上,你可能猜到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以获取令牌,尽管可能有替代方法来获取合适的令牌。