导语:在软件行业,可用性和安全性一直是个矛盾。许多第三方程序可以通过存储用户的凭据方便用户使用。然而,事实证明,这种便利通常是以安全性性为代价的,从而导致密码被盗的风险。以这种方式收集的凭据可以在实际的网络攻击期间使用。
在软件行业,可用性和安全性一直是个矛盾。许多第三方程序可以通过存储用户的凭据方便用户使用。然而,事实证明,这种便利通常是以安全性性为代价的,从而导致密码被盗的风险。以这种方式收集的凭据可以在实际的网络攻击期间使用。
攻击者如何扩展其访问权限
很明显,凭据盗窃是很危险的。但是,有必要强调凭据盗窃可能产生的影响规模。
许多人倾向于在不同的程序中使用相同的密码,并且很少更改他们的密码。到了修改密码的时候,许多人都遵循可预测的模式。
因此,当攻击者可以从一个来源获得密码时,他们可以尝试使用它来攻击其他资源,包括一些更受保护的资源。因此,对于每个安全的程序 A,用户可以在不太安全的程序 B 上使用相同的密码或模式,这可能导致程序 A 的安全性降低。
此外,如果发现有人在其他不太安全的地方使用他们的操作系统密码,那么攻击者就会打开一个全新的可能性世界。
例如,假设某人 X 对他的 Windows 帐户域和 Linux FTP 文件服务器使用相同的密码。在这种情况下,X用户使用常用程序WinSCP在文件服务器上管理自己的文件。尽管 WinSCP 建议不建议保存密码,但是X用户每周都会访问这个文件服务器,所以他们更愿意节省时间,保存密码。
WinSCP 不建议保存密码
正如我们稍后将演示的那样,用户的密码可以很容易地从WinSCP存储密码的地方获取。可以在 X 的个人计算机上立足的攻击者可以获得他们的域帐户密码,只是因为它被不安全地保存了。最重要的是,密码对于连接到文件服务器是有效的。该文件服务器可能包含攻击者现在可以访问的敏感信息文件。那样,攻击者可以使用像 BloodHound 这样的工具来估计他们可以在一个组织内传播多远。
以WinSCP为例进行具体分析
WinSCP是常用的一种SFTP客户端和FTP客户端,用于在Windows本地计算机和远程服务器之间通过FTP、FTPS、SCP和SFTP复制文件。
测试版本:5.19.6 (Build 12002 2202-02-22)
凭据存储在哪里?
WinSCP将加密后的用户密码存储在如下所示的注册表项下的一个名为 Password 的值中。
如何恢复凭据?
WinSCP工具对用户密码的位数进行对称数学运算。它获取密码的每个字节,计算0xFF(11111111)的补码,然后用字节0xA3(10100011)对其进行异或运算。
加密过程包括找到补码并执行一次异或运算。然后将密码存储在密码注册表值中。由于这些数学运算是对称的,我们需要做的就是以相反的顺序再次执行相同的两个运算,以获得原始值。
例如,让我们以一个常用的密码为例:Aa123456。“1D3D6D6E6F68696A”密码在WinSCP工具上的存储方式如下。
在下图中,我们看到了解密密码的步骤:
解密存储在 WinSCP 中的密码
密码与主机名和用户名一起保存。要从密码注册表值中获取它,我们必须找到密码开头的索引。这个计算非常简单,根据WinSCP版本,注册表值的第一个或第三个字节是连接的用户名、主机名和密码的长度。起始索引是长度的下一个字节,其值乘以 2。长度和起始索引都以相同的方式加密。
主机名和用户名也保存在不同的注册表值上,因此我们知道它们的长度和值。我们所做的就是从索引中解密密码注册表的值:开始索引+用户名长度+主机名长度,我们就会得到我们的密码。
连接的用户名、主机名和密码的位置
野外利用
我们已经看到在多个客户环境中执行了以下脚本:
可疑的PowerShell编码命令
-enc表示EncodedCommand,这意味着将使用一个base-64编码的字符串作为命令。
在解码的脚本中,我们可以看到尝试解密 WinSCP 密码:
用于提取和解密 WinSCP 密码的 PowerShell 脚本
Cortex XDR阻止了读取存储在WinSCP中的密码的尝试
以Git为例进行具体分析
测试版本:2.35.1.windows.2。
凭据存储在哪里?
Git 允许同时使用密码和个人访问令牌 (PAT)。
当用户想通过保存他们的Git凭据来节省时间时,他们可以使用以下命令:
git config credential.helper 'store'
使用这个命令,Git将以纯文本的形式无限期地将用户的凭据保存在磁盘上。
可能包含密码的文件:
Git 允许使用 PAT 作为凭据,而不是传统的密码使用。这些令牌更加模块化,因为可以创建任意数量的访问令牌,每个令牌具有不同的权限和过期日期。
虽然可以以更模块化和更细粒度的方式控制用户的操作,每个操作都与特定的 PAT 相关联,但是拥有用户PAT的任何人都可以查看用户可以访问的所有存储库。
这些标签也以明文形式出现在上面提到的相同文件中。
如何恢复凭据?
任何阅读这些文件的人都会以纯文本形式看到用户名、密码或令牌以及相关的 Git 存储库。
以RDCMan为例进行具体分析
测试版本:2.83
RDCMan可以管理多个远程桌面连接。它对于管理需要定期访问计算机的服务器实验室非常有用,比如自动签入系统和数据中心。
凭据存储在哪里?
当用户决定使用 RDCMan 保存会话密码时,默认配置文件将为 %localappdata%\Microsoft\Remote Desktop Connection Manager\RDCMan.settings。
这个文件是一个XML文件,包含关于每个RDP连接的通用元数据。在这些数据中,有一个名为CredentialsProfiles的XML标签引起了我们的注意。
我们可以看到,在这个标签下,还有另一个名为CredentialsProfiles的标签,其中还有credentialsProfile XML标签,以及一个 Password 标签。
查看RDCMan.settings中的XML标签
如何恢复凭据?
要检索密码,我们必须在使用RDCMan程序的用户的上下文中执行命令。这是因为密码是使用数据保护API (DATA Protection API, DPAPI)保存的,该 API 可以分别使用CryptProtectData和CryptUnprotectData函数对任何类型的数据进行对称加密和解密。
因此,为了获得密码,我们需要调用CryptUnprotectData函数。
通常,唯一可以解密数据的用户是与加密数据的用户具有相同登录凭据的用户。
尽管从 RDCMan 收集凭据需要攻击者采取比我们其他一些示例中所需的额外步骤,在相关用户的上下文中运行软件,但结果对攻击者来说具有很大的价值。如果成功,攻击者就有可能获得该特定用户连接到的所有计算机的所有用户和密码。
一旦攻击者能够在用户的上下文中执行命令,为了收集凭据,剩下要做的就是:
打开 RDCMan.settings 文件并检查密码 XML 标签;
使用 base64 解码标签中的字符串;
使用解码的密码字符串调用 CryptUnprotectData;
使用 UTF-8(或其他相关格式)对结果进行解码;
删除不必要的空字符;
看看上面的例子,保存在文件中的密码是:
AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA8/nnW5aFNUi0AKiTG4y9UQAAAAACAAAAAAAQZgAAAAEAACAAAADIjLLw0X4z9RDdWgPpqabLU7hTcJ1HVlFklpzX3eA14QAAAAAOgAAAAAIAACAAAAB01OvDCNCjaEhrq8J8hRm/SKycef7nR52ZkqcPLJqMsCAAAACg2htaeRsutDziS3FISeEAg3DsBpGxBGpPeWlUSVnXOkAAAAB5Tei9g5KWcVIhOKQ2cXxr5ONUOHMEEH5h3Lmp12mPlWaaZ6y8dGIVz8WnNKr4e73dhqNU8NyzI7RZBamS6DG6
解密后的密码是Aa123456。
从RDCMan中恢复密码
以OpenVPN为例进行具体分析
测试版本:2.5.029。
OpenVPN 是一个虚拟专用网络系统,它实现了在路由或桥接配置和远程访问设施中创建安全的点对点连接的技术。
凭据存储在哪里?
OpenVPN 将用户的密码存储在如下所示的注册表项下的一个名为 auth-data 的值中。
如何恢复凭据?
OpenVPN还使用了DPAPI机制,并附加了可选的熵参数(可以设置为 NULL)。
当在加密阶段使用可选的熵DATA_BLOB结构时,必须在解密阶段使用相同的DATA_BLOB结构。
在OpenVPN的情况下,熵保存在一个名为熵的注册表值中。熵注册值也存储在如下路径。
因此,使用来自 auth-data 和 熵(来自熵)的密码调用 CryptUnprotectData 将为我们提供会话密码。
熵注册表值包含一个额外的字节00,所以我们只需要省略它。
上面是恢复OpenVPN密码的PowerShell脚本。下面,通过 reg.exe (POC) 显示 auth-data 和 entropy 注册表值的方式。
以基于 Chromium 的浏览器为例进行具体分析
测试版:
Google Chrome——测试版本:103.0.5060.53(官方版本)(64 位);
Microsoft Edge——测试版本:103.0.1264.37(官方版本)(64 位);
Opera——测试版本:88.0.4412.53;
Chromium 项目包括 Chromium,它是 Google Chrome 浏览器背后的开源项目。
在典型的使用例程中,许多人倾向于在上网时保存密码。
Google Chrome 版本 102.0.5005.115(官方版本)(64 位)保存的密码
凭据存储在哪里?
在使用基于 Chromium 的浏览器(如 Microsoft Edge、Opera 或 Google Chrome)时,密码被加密位于 SQLite 数据库文件中,通常称为登录数据。
每个配置文件都有一个密码数据库,即它的登录数据文件。
用于加密密码的密钥位于父文件夹中的名为本地状态的 JSON 文件中。
例如:
登录数据位置:
区域位置:
Google Chrome: %localappdata%\google\chrome\user data\local state
Microsoft Edge: %localappdata%\microsoft\edge\user data\local state
Opera: %appdata%\opera software\opera stable\local state
如何恢复凭据?
登录数据库中的每个密码都使用高级加密标准 (AES) 以 GCM 模式进行加密。AES GCM是一种对称加密方法,因此相同的密钥对加密和解密都有效。AES算法对每个128位数据块使用不同的密钥,该密钥基于前一个块的计算。对于第一个块,可以选择使用初始化向量 (IV)。
要解密基于 Chromium 的浏览器保存的密码,我们需要:
加密的密码;
初始化向量;
AES 密钥;
让我们看看如何检索它们:
加密密码
可以从登录数据数据库中导出:加密的密码从password_value列中取出,从第15位的字母到末尾的16个字母。[15:-16]
初始化向量
位于相同的 password_value 字段列中,从第 3 位的字母到第 15 位的字母。[3:15]
AES密钥
写在本地状态 JSON 文件中,在密钥 os_crypt 和 encrypted_key 下,用 base64 解码。
基于 Chromium 的浏览器使用 DPAPI 机制保存 AES 密钥,因此要获取它,我们必须从 base64 解码它并在用户的上下文中使用 CryptUnprotectData。
来自谷歌Chrome的示例:
保存在 Google Chrome 本地状态 JSON 文件中的密码
它以五个字母开头的前缀保存:DPAPI。
保存在 Google Chrome 中的解码密码
如果攻击者能够在用户的上下文中运行,那么完成收集用户凭据所需要做的就是:
复制登录数据和本地状态文件;
从本地状态JSON文件中获取AES GCM密钥;
解码(base64),解密(CryptUnprotectData)并从密钥中删除填充;
使用解密的 AES GCM 密钥解密登录数据数据库中的每个密码;
用于恢复 Chrome 中保存的密码的 POC
你可以阅读有关如何在 Python 中提取 Chrome 密码的更多信息。
野外利用
我们看到在excel.exe中使用regsvr32.exe运行了以下DLL:
(kgnkudbadmpogg.dll 的 SHA256:6599FEE8C7ADF30A00889A7070600F472F8CEAD8EA4DD1A85E724ED15F2AED0F)
在一系列操作之后,最终的有效负载试图访问 Microsoft Edge 凭据文件:
登录数据文件(SQLite 数据库文件)如下所示:
本地状态文件(包含加密密钥)如下所示:
Cortex XDR 检测到读取保存在 Microsoft Edge 浏览器中的密码的尝试
以Firefox浏览器为例进行具体分析
测试版本:Firefox 版本 101.0.1(64 位)
使用其他浏览器(例如 Mozilla Firefox)时,密码保存行为模式也很重要。
Firefox 版本 101.0.1(64 位)保存的密码
凭据存储在哪里?
与基于 Chromium 的浏览器类似,在 Mozilla Firefox 浏览器中,每个配置文件也有自己的密码文件。
此文件名为 logins.json,位于以下位置中:
用户名和密码均以加密方式保存。
Firefox 的 logins.json 文件中保存的密码
如何恢复凭据?
logins.json 文件中的每个用户名和密码都使用 PKCS #11 加密标准进行加密。 Firefox 开发了 NSS 库,以便在其浏览器 (nss3.dll) 中采用此标准。
NSS 将私钥存储在名为 key3.db 或 key4.db 的文件中,具体取决于 NSS 版本。
要检索用户的密码,攻击者必须访问其中一个文件和logins.json 文件。
因此,如果攻击者能够获得在同一台计算机上运行的权限,那么窃取密码的过程将是:
攻击者复制 logins.json 文件;
加载 NSS 库 (nss3.dll);
从 logins.json 的副本中解码(base64) encryptedUsername 和 encryptedPassword;
将每个输入存储在一个 SecItem 对象中,该对象稍后在整个 NSS 中用于来回传递二进制数据块;
创建用于输出的 SecItem 对象;
使用 nss3.dll 中的 PK11 解密函数解密每个 encryptedUsername 和 encryptedPassword 输入对象,并将数据存储在新的 SecItem 输出对象中;
与基于 Chromium 的浏览器的情况不同,攻击者不必在用户的上下文中运行以获取用户的密码,而是可以利用任何有权访问目标用户的文件系统配置文件的用户。
用户 S 获得了属于用户 D 的密码,这些密码保存在 Firefox 配置文件 2 中
野外利用
我们已经看到执行了以下脚本:
可疑的混淆 PowerShell 脚本
解码后:
反混淆的 PowerShell 脚本
脚本:
创建文件夹%localappdata%\ujXgAD;
尝试为$ links中的每个链接创建Invoke-WebRequest,下载一个DLL并将其保存在第一步中提到的文件夹中,名称为rRXqwGvGNR.wTj;
在第一次成功执行后中断;
接下来,我们看到在终端上创建了一个DLL,并用以下命令行使用了regsvr32.exe:
请注意,路径中有一个规避:通过使用 \..\ 返回本地文件夹,攻击者避免直接访问它。
使用 regsvr32.exe 后:
1.DLL 将自身复制到具有随机名称的随机文件夹,带有 DLL 扩展名:
2.DLL 执行几个发现命令:
Systeminfo——列出计算机信息;
ipconfig /all——列出计算机上的所有网络接口;
nltest.exe /dclist:——列出域内所有域控制器;
3.DLL 基于 certutil.exe 创建并执行两个随机名称的文件:
其中一个有一个新的随机名称,但仍由 Microsoft 签名;
另一个是 certutil 的修改版本,它保留了原始名称,但具有不同的功能,并且没有签名;
4.上述步骤 C 进行两次。
未签名文件 SHA256:
A88C344F3F80F8A3EA2E9BA0687FEBCEE2A730FD9AC037D54C4FD21C0AB91039
Certutil SHA256(请注意,此文件是良性的):
D252235AA420B91C38BFEEC4F1C3F3434BC853D04635453648B26B2947352889
未签名的 certutil.exe 会尝试访问基于 Chromium 和Firefox 的浏览器的密码文件。
检查上图中的链接时,只有两个链接有效:
能够下载的 DLL
首先下载的DLL:
hxxps://www[.]yell[.]ge/nav_logo/AEnTP/
下载文件名:RwuuPYoVei7FkJB.dll
(SHA256:A1D513E4A5C83895E5769C994C4D319959EF5AE3F679CE6C0C5211B5BECA7695)
第二次下载的DLL:
hxxps://yakosurf[.]com/wp-includes/S/
下载文件名:lw1JF63zARLUV8UwpwGnWpgg.dll
(SHA256:1B8638333751EFCB6B5332C801C11DF0DE3D7077C6ACEA1D663C0302519D7172)
在这两种情况下,它实际上是同一个 DLL,除了改变 SHA256 哈希值的微小差异。
通过查看此样本,我们将第一个 DLL 确定为 Emotet 恶意软件家族的一部分。
Cortex XDR阻止了读取保存在Firefox浏览器中的密码的尝试
Cortex XDR 同步停止此操作,因此不会执行下一个攻击阶段。该恶意软件尝试按以下顺序读取密码:首先是 Firefox,然后是 Microsoft Edge,然后是 Google Chrome。
为了演示,我们将使用报告模式说明 Cortex XDR。我们将看到凭据收集保护模块还检测到读取基于 Chromium 的浏览器保存的密码的尝试。
Cortex XDR 检测到读取保存在 Microsoft Edge 浏览器中的密码的尝试
Cortex XDR 检测到读取保存在 Google Chrome 浏览器中的密码的尝试
Emotet?
由于我们看到了两个涉及 Emotet 的不同案例,因此我们更深入地研究了这个恶意软件家族及其用于第三方凭据收集的方法。我们看到,有时恶意软件甚至不需要自己实现所有逻辑条件。它可以包装现有工具,例如 WebBrowserPassView Nirsoft 工具,以显示 Web 浏览器存储的密码。
WebBrowserPassView.exe显示用户名、密码和存储它们的文件路径
我们可以看到基于 Chromium 的浏览器的登录数据文件,以及 Firefox 浏览器的 logins.json 文件。
Cortex XDR阻止试图通过WebBrowserPassView.exe读取浏览器保存的密码
总结
事实证明,某些第三方软件存储凭据的方式不如我们想象的安全。大多数这些程序通过文件或注册表值将用户凭据存储在本地磁盘上。这一事实可能是攻击者希望找到的链中的一个弱点,使他们能够对组织实施攻击。
本文翻译自:https://unit42.paloaltonetworks.com/credential-gathering-third-party-software/如若转载,请注明原文地址