Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
vbox-vmdk-sparse-extent — Oracle VM VirtualBox 7.2.20 - 高危 - 本地 - 文件读取 - VMDK 稀疏 FLAT extent 路径拼接 | Kitploit
工具/GitHubGitHub/abraxas/vbox-vmdk-sparse-extent
漏洞分析漏洞利用Web应用程序漏洞利用安全虚拟化渗透测试实验室与实践
GitHubabraxas/vbox-vmdk-sparse-extent

vbox-vmdk-sparse-extent

Oracle VM VirtualBox 7.2.20 - 高危 - 本地 - 文件读取 - VMDK 稀疏 FLAT extent 路径拼接

查看仓库
22天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Abraxas Labs - vbox-vmdk-sparse-extent

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  vbox-vmdk-sparse-extent

vbox-vmdk-sparse-extent

类别: 文件读取 触达范围: 本地(主机)UI:R

Oracle VM VirtualBox OSS 7.2.20 (f2792cf44) - Oracle

当主机用户导入一个 OVF 目录或 OVA,且其磁盘由一个稀疏 VMDK 描述符加一个 FLAT extent 组成时,程序会打开该 extent 中指定的主机路径,并将这些字节复制到导入的磁盘中。在 vmdkParseDescriptor 之后,每个 pszBasename 以 RTPATH_SLASH 开头的 extent 会被直接使用;否则会调用 RTPathJoinA(descriptor dir, pszBasename),该调用会跟随 ../。随后 FLAT 和 HOSTED_SPARSE 会通过 vmdkFileOpen 打开该完整路径。streamOptimized(VirtualBox 常规导出格式,VMDK 魔数)是单个文件,不会走这条路径。导入过程仍然接受稀疏说明符。

ID暂无 CVE
类别文件读取(稀疏 VMDK FLAT/稀疏 extent 路径)
触达范围本地(主机) UI:R(受害者导入恶意设备)
CWECWE-22
CVSS高危:7.7 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
产品Oracle VM VirtualBox OSS
受影响版本7.2.20 (f2792cf44f663989818507e36d3db5f978523c5e)
认证VirtualBox 上无需认证。主机用户打开 File/Import 或执行 VBoxManage import。
许可证GNU Affero GPL v3.0
实验环境仅 127.0.0.1。源码测试框架。VirtualBox 未启动。

攻击者能做什么

提供一个 OVF 目录或 OVA。将一个稀疏 VMDK 描述符(# Disk DescriptorFile、createType="monolithicFlat")与一个 FLAT extent 放在一起,该 extent 的带引号基名为 ../../somewhere/secret 或 /path/secret。导入该设备的操作者会以导入用户的 UID 打开该主机路径,并将字节复制到目标磁盘中。streamOptimized(VMDK 魔数 0x564D444B)不会参考内嵌的 FLAT 名称。这是对 VBox UID 可打开文件的读取,而不是对 authorized_keys 的无后缀写入。

权限方法 + 汇聚点授予的能力来源
侦察导入一个 ASCII 稀疏 VMDK。在 vmdkParseDescriptor 之后,执行 RTPathJoinA(descriptor dir, pszBasename),且不折叠 ../(VMDK.cpp 3472-3503)。对该完整路径执行 FLAT vmdkFileOpen。导入会将这些字节复制到 dest。由 ../ 指定的主机文件字节落入导入的磁盘中。实验中将 pszBasename 设为 ../../oracle/VBOX-VMDK-SPARSE-EXTENT-WITNESS,与 /work/import/disk/../../oracle/... 拼接,并复制到 /work/import/out.vmdk。实验证实(relative-escape=yes)
侦察同样的路径遍历。pszBasename[0] == RTPATH_SLASH 被原样使用(VMDK.cpp 3477-3485)。打开并复制绝对主机路径。实验中为 /work/oracle/VBOX-VMDK-SPARSE-EXTENT-WITNESS。实验证实(absolute-extent=yes)
侦察对照 FLAT disk-flat.vmdk 拼接在描述符目录下。保持在文件夹内。实验中的完整路径为 /work/import/disk/disk-flat.vmdk。字节为 CONTROL-FLAT-NOT-ORACLE。实验证实(control-in-folder=yes)
侦察带 VMDK magic 的 streamOptimized。vmdkDescriptorRead 调用 vmdkDescriptorReadSparse。内嵌的 ASCII FLAT 指定了 oracle。未打开内嵌名称。dest 仍为流文件(STREAMOPTIMIZED-SELF-NOT-ORACLE)。实验证实(streamoptimized-consults-extent=no)
侦察客户机启动,然后读取转换后的卷。客户机看到导入器 UID 可读的主机文件内容,这些内容已落入 dest。推断(同一复制过程;实验未启动客户机)
可用性导入的 dest 已存在,或之后挂载转换后的磁盘。覆盖 dest 磁盘的可用性。内容变为被打开的主机文件。推断(同一 dest 写入)
已排除streamOptimized VMDK(VirtualBox 常规导出)Magic 分支。单文件。内嵌 FLAT 名称不会被打开。已排除
已排除Windows 盘符绝对路径(C:\...)可能漏掉 pszBasename[0] == RTPATH_SLASH。代码将绝对路径检查称为 hack(@todo implement proper path absolute check)。已排除
已排除无后缀写入(authorized_keys、crontab)不是写入残留。extent 打开是对指定主机路径的读取。已排除
已排除主机内核、客户机到主机、其他虚拟机、VBoxSVC 内存不是此残留。复制不需要启动虚拟机。与导入器相同的 UID。已排除

一旦稀疏描述符位于磁盘上,OVA 就是同样的路径遍历:tar 成员提供描述符以及(可选的)文件夹内 FLAT;extent 的 basename 提供逃逸的打开操作。不涉及 3D、不涉及 Guest Additions、不涉及 VRDP、不涉及 PUEL。

我是如何发现的

在 2026 年 9 月的 CPU 之后,我停留在标签 v7.2.20(f2792cf44)上,并阅读了 VMDK 导入相关代码。ExtraData、共享文件夹、NVRAM dest 和串口 RawFile 都已被剥离。ovf:href dest 是同级残留。VirtualBox 常规导出是 streamOptimized。interpret() 仍然接受稀疏说明符(g_pszVMDKSparseURI)。在 vmdkParseDescriptor 之后,extent 的 basename 被拼接,既不折叠 ../,也不拒绝绝对路径:

/* Hack to figure out whether the specified name in the
 * extent descriptor is absolute. Doesn't always work, but
 * should be good enough for now. */
char *pszFullname;
/** @todo implement proper path absolute check. */
if (pExtent->pszBasename[0] == RTPATH_SLASH)
{
    pszFullname = RTStrDup(pExtent->pszBasename);
    /* ... */
}
else
{
    char *pszDirname = RTStrDup(pImage->pszFilename);
    RTPathStripFilename(pszDirname);
    pszFullname = RTPathJoinA(pszDirname, pExtent->pszBasename);
    /* ... */
}
pExtent->pszFullname = pszFullname;

RTPathJoinA 仅平衡斜杠。它不会折叠 ..。随后 FLAT 和 HOSTED_SPARSE 会打开该字符串:

case VMDKETYPE_FLAT:
    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
                      VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */));

vmdkDescriptorRead 按 magic 进行分支。VMDK 稀疏 magic(0x564D444B)走 vmdkDescriptorReadSparse,并将已打开的文件保留为 extent。ASCII 走 vmdkDescriptorReadAscii 以及上面的 join。

已记录的弯路:将 streamOptimized 当作这种残留情况处理(magic 不会查询内嵌的 FLAT 名称);将 Windows 盘符绝对路径当作 Unix 斜杠检查;将 dest-disk 覆盖当作无后缀的 authorized_keys 写入;在 join 的源 harness 已足够时启动 VM。表演性:宿主内核、guest 到 host。判定依据是描述符文件夹之外的一条见证行,外加一个保持原位的对照 disk-flat.vmdk。

实验环境

python3 vbox-vmdk-sparse-extent-Abraxas-Labs.py

或

cd lab
./run.sh

vmdkParseDescriptor extent join、vmdkFileOpen 以及 streamOptimized magic 分支的源 harness。Docker compose,回环地址 127.0.0.1:19250,无 VirtualBox 二进制文件。描述符目录 /work/import/disk。Oracle /work/oracle。目标 /work/import/out.vmdk。

SUCCESS vbox-vmdk-sparse-extent relative-escape=yes absolute-extent=yes control-in-folder=yes VBOX-VMDK-SPARSE-EXTENT-WITNESS

修复方案

在 pszBasename 中折叠或拒绝 ..。拒绝绝对路径的 pszBasename。或者仅在描述符目录下打开 extent(RTPATHABS_F_STOP_AT_BASE / realpath-under-base)。不要将 pszBasename[0] == RTPATH_SLASH 视为完整的绝对路径检查。

参考资料

  • github.com/VirtualBox/virtualbox 标签 v7.2.20(f2792cf44f663989818507e36d3db5f978523c5e)
  • VMDK.cpp vmdkDescriptorReadSparse 3312,vmdkDescriptorReadAscii extent 拼接 3472-3547,vmdkDescriptorRead 3576-3589
  • ApplianceImpl.cpp g_pszVMDKSparseURI 61, 78
  • ApplianceImplImport.cpp i_importOneDiskImage 4343-4408
  • CWE-22

许可证

GNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。不提供任何担保。

下载工具