CVE-2023-32784的原始概念验证(PoC)
作者:Sec-Labs | 发布时间:
项目地址
https://github.com/vdohney/keepass-password-dumper
KeePass 2.X主密码转储工具(CVE-2023-32784)
更新
该漏洞已被分配为CVE-2023-32784。应该在KeePass 2.54中修复,该版本预计将于2023年6月初发布。再次感谢Dominik Reichl的快速响应和创造性修复!
澄清:密码必须通过键盘输入,而不是从剪贴板复制(请参阅"How it works"部分)。
你可以做什么
首先,在可用时升级到KeePass 2.54或更高版本。
其次,如果您长时间使用KeePass,您的主密码(以及可能的其他密码)可能存在于您的页面文件/交换文件、休眠文件和崩溃转储文件中。根据您的偏执症程度,您可以考虑以下步骤来解决该问题:
- 更改您的主密码。
- 删除崩溃转储文件(取决于您的操作系统,在Windows上至少为
C:\Windows\memory.dmp,但可能还有其他文件)。 - 删除休眠文件。
- 删除页面文件/交换文件(可能会很麻烦,请不要忘记重新启用)。
- 覆盖硬盘上的已删除数据以防止数据恢复(例如,在Windows上使用带有
/w选项的Cipher命令)。 - 重新启动计算机。
或者只需覆盖您的硬盘并对操作系统进行全新安装。
以下是不受影响的产品(请创建拉取请求或问题以添加更多)。一般准则是,如果它不是使用.NET编写的原始KeePass 2.X应用程序,则可能不受影响。
KeePass主密码转储工具是一个简单的概念验证工具,用于从KeePass的内存中转储主密码。除了第一个密码字符外,它基本上可以以明文形式恢复密码。不需要在目标系统上执行代码,只需进行内存转储。内存的来源不重要-可以是进程转储、交换文件(pagefile.sys)、休眠文件(hiberfil.sys)、各种崩溃转储文件或整个系统的RAM转储。工作空间是否锁定并不重要。即使在KeePass不再运行时,也可以从RAM中转储密码,尽管该方法成功的可能性会随着时间的推移而降低。
在Windows(英语)上使用KeePass 2.53.1和Debian(keepass2包)上的KeePass 2.47进行了测试。它应该也适用于macOS版本。不幸的是,启用"在安全桌面上输入主密钥"选项无助于防止此攻击。概念验证工具在处理旧版本KeePass创建的数据库时可能会遇到问题,但我无法复现该问题(请参见issue #4)。
Dominik Reichl,KeePass的作者,在此处确认了该发现。我对Dominik的快速回应表示赞赏。希望问题能够尽快修复!
设置
- 安装.NET(支持大多数主要操作系统)。
- 运行
dotnet run PATH_TO_DUMP。
在Windows上进行测试的最简单方法是通过任务管理器右键单击KeePass进程并选择"创建转储文件"来创建进程转储。

- 或者,您可以添加另一个参数
dotnet run PATH_TO_DUMP PATH_TO_PWDLIST来生成从第二个字符开始的所有可能密码的列表。
你是否应该担心?
这取决于您的威胁模型。如果您的计算机已经感染了在后台以您用户的权限运行的恶意软件,这个发现不会使您的情况变得更糟。然而,由于与KeeTheft或KeeFarce不同,不需要进行进程注入或其他类型的代码执行,因此恶意软件可能更容易偷偷行动并逃避杀毒软件。
如果您有合理的怀疑有人可能获取对您计算机的访问权限并进行取证分析,那么情况可能不太妙。最糟糕的情况是,即使KeePass被锁定或根本没有运行,主密码也会被恢复。
如果您使用具有强密码的全磁盘加密,并且您的系统是干净的,那么应该没问题。单凭这个发现,没有人能够通过互联网远程窃取您的密码。
工作原理
KeePass 2.X使用自定义开发的文本框进行密码输入,称为SecureTextBoxEx。这个文本框不仅用于主密码输入,还用于KeePass中的其他地方,如密码编辑框(因此该攻击也可以用于恢复其内容)。
这里利用的漏洞是,对于每个键入的字符,都会在内存中创建一个剩余字符串。由于.NET的工作方式,一旦创建了这些字符串,几乎不可能摆脱它们。例如,当键入"Password"时,会产生以下剩余字符串:•a,••s,•••s,••••w,•••••o,••••••r,•••••••d。POC应用程序在转储中搜索这些模式,并为密码中的每个位置提供一个可能的密码字符。
这种攻击的可靠性可能会受到输入密码的方式以及每个会话中键入的密码数量的影响。然而,我发现,即使在会话中有多个密码或存在打字错误,.NET CLR分配这些字符串的方式意味着它们很可能在内存中被很好地排序。因此,如果键入了三个不同的密码,您很可能会按照顺序获得每个字符位置的三个候选密码,这使得可能恢复所有三个密码。
开发
这只是一个快速的概念验证,所以可能不是非常可靠和健壮。如果您发现了问题并修复了它,请创建一个拉取请求。
目前,允许的密码字符是硬编码的,如下所示:^[\x20-\x7E]+$(所有可打印的ASCII字符和空格)。
致谢
感谢adridlug添加了自动生成密码列表的功能,以及ynuwenhof重构了代码。
相关项目
- Python实现的PoC,由CMEPW贡献
- Rust实现的PoC,由ynuwenhof贡献
我还没有检查过它们中的任何一个。