
Oracle VM VirtualBox 7.2.20 – Hoch – Lokal – Dateilesen – VMDK sparse FLAT extent path join
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vbox-vmdk-sparse-extent
Klasse: Dateilesen Reichweite: Lokal (Host) UI:R
Oracle VM VirtualBox OSS 7.2.20 (f2792cf44) - Oracle
Ein Host-Benutzer, der ein OVF-Verzeichnis oder eine OVA importiert, deren Disk ein sparse VMDK-Deskriptor plus FLAT-Extent ist, öffnet einen in diesem Extent benannten Host-Pfad und kopiert diese Bytes in die importierte Disk. Nach vmdkParseDescriptor wird jedes Extent, dessen pszBasename mit RTPATH_SLASH beginnt, unverändert verwendet; andernfalls RTPathJoinA(descriptor dir, pszBasename), was ../ folgt. FLAT und HOSTED_SPARSE rufen dann vmdkFileOpen mit diesem vollständigen Pfad auf. streamOptimized (üblicher VirtualBox-Export, VMDK-Magic) ist eine einzelne Datei und durchläuft diesen Pfad nicht. Der Import akzeptiert dennoch den sparse-Spezifizierer.
| ID | noch keine CVE |
| Klasse | Dateilesen (sparse VMDK FLAT/sparse-Extent-Pfad) |
| Reichweite | Lokal (Host) UI:R (Opfer importiert eine feindliche Appliance) |
| CWE | CWE-22 |
| CVSS | Hoch: 7.7 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N |
| Produkt | Oracle VM VirtualBox OSS |
| Betroffen | 7.2.20 (f2792cf44f663989818507e36d3db5f978523c5e) |
| Auth | keine bei VirtualBox. Der Host-Benutzer öffnet Datei/Importieren oder VBoxManage import. |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1. Source-Harness. VirtualBox wird nicht gebootet. |
Liefere ein OVF-Verzeichnis oder eine OVA aus. Platziere einen sparse VMDK-Deskriptor (# Disk DescriptorFile, createType="monolithicFlat") neben einem FLAT-Extent, dessen zitierter Basisname ../../somewhere/secret oder /path/secret lautet. Der Operator, der ihn importiert, öffnet diesen Host-Pfad mit der importierenden UID und kopiert die Bytes in die Ziel-Disk. streamOptimized (VMDK-Magic 0x564D444B) konsultiert den eingebetteten FLAT-Namen nicht. Dies ist ein Lesen von Dateien, die die VBox-UID öffnen kann, kein suffixfreies Schreiben von authorized_keys.
| Berechtigung | Methode + Sink | Was sie gewährt | Herkunft |
|---|---|---|---|
| Recon | Import einer ASCII-sparse-VMDK. Nach vmdkParseDescriptor erfolgt RTPathJoinA(descriptor dir, pszBasename) ohne ../-Auflösung (VMDK.cpp 3472-3503). FLAT vmdkFileOpen dieses vollständigen Pfads. Der Import kopiert diese Bytes in das Ziel. | Host-Dateibytes, die durch ../ benannt werden, landen in der importierten Disk. Im Lab wurde pszBasename ../../oracle/VBOX-VMDK-SPARSE-EXTENT-WITNESS mit /work/import/disk/../../oracle/... zusammengeführt und nach /work/import/out.vmdk kopiert. | Im Lab nachgewiesen (relative-escape=yes) |
| Recon | Derselbe Walk. pszBasename[0] == RTPATH_SLASH wird unverändert verwendet (VMDK.cpp 3477-3485). | Absoluter Host-Pfad geöffnet und kopiert. Im Lab /work/oracle/VBOX-VMDK-SPARSE-EXTENT-WITNESS. | Im Lab nachgewiesen (absolute-extent=yes) |
| Recon | Kontroll-FLAT disk-flat.vmdk, zusammengeführt unter dem Descriptor-Verzeichnis. | Bleibt im Ordner. Im Lab lautet der vollständige Name /work/import/disk/disk-flat.vmdk. Bytes CONTROL-FLAT-NOT-ORACLE. | Im Lab nachgewiesen (control-in-folder=yes) |
| Recon | streamOptimized mit VMDK-Magic. vmdkDescriptorRead verwendet vmdkDescriptorReadSparse. Eingebettetes ASCII-FLAT benannte das Oracle. | Der eingebettete Name wurde nicht geöffnet. Das Ziel blieb die Stream-Datei (STREAMOPTIMIZED-SELF-NOT-ORACLE). | Im Lab nachgewiesen (streamoptimized-consults-extent=no) |
| Recon | Guest Start, dann das konvertierte Volume lesen. | Der Gast sieht Host-Dateiinhalte, die für die UID des Importers lesbar sind und im Ziel gelandet sind. | Abgeleitet (gleiche Kopie; das Lab startet keinen Gast) |
| Verfügbarkeit | Import-Ziel, das bereits existiert, oder ein späteres Anhängen der konvertierten Disk. | Überschreibt die Verfügbarkeit der Ziel-Disk. Die Inhalte werden zur geöffneten Host-Datei. | Abgeleitet (gleiches Schreiben des Ziels) |
| Geschlossen | streamOptimized VMDK (üblicher VirtualBox-Export) | Magic-Zweig. Einzelne Datei. Der eingebettete FLAT-Name wird nicht geöffnet. | Geschlossen |
| Geschlossen | Windows-Laufwerksbuchstaben-Absolutpfad (C:\...) | Kann pszBasename[0] == RTPATH_SLASH verfehlen. Der Code bezeichnet die Absolutpfad-Prüfung als Hack (@todo implement proper path absolute check). | Geschlossen |
| Geschlossen | Suffixfreie Schreibvorgänge (authorized_keys, crontab) | Kein Schreib-Überbleibsel. Das Öffnen des Extents ist ein Lesen des benannten Host-Pfads. | Geschlossen |
| Geschlossen | Host-Kernel, Gast-zu-Host, andere VMs, VBoxSVC-Speicher | Nicht dieses Überbleibsel. Für die Kopie ist kein VM-Start erforderlich. Gleiche UID wie der Importer. | Geschlossen |
OVA ist derselbe Walk, sobald der sparse Descriptor auf der Festplatte liegt: Das tar-Mitglied liefert den Descriptor plus (optional) FLAT im Ordner; der Extent-Basename liefert das escaped Öffnen. Kein 3D, keine Guest Additions, kein VRDP, nicht PUEL.
Ich blieb nach der CPU vom Sep 2026 auf Tag v7.2.20 (f2792cf44) und las den VMDK-Import. ExtraData, Shared Folders, NVRAM-Ziel und serielles RawFile sind bereits entfernt. Das ovf:href-Ziel ist ein benachbartes Überbleibsel. Der übliche VirtualBox-Export ist streamOptimized. interpret() akzeptiert weiterhin den sparse-Spezifizierer (g_pszVMDKSparseURI). Nach vmdkParseDescriptor wird der Extent-Basename zusammengeführt, ohne ../ aufzulösen oder absolute Pfade abzulehnen:
/* 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 gleicht nur Schrägstriche aus. Es fasst .. nicht zusammen. FLAT und HOSTED_SPARSE öffnen dann diesen String:
case VMDKETYPE_FLAT:
rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */));
vmdkDescriptorRead teilt am Magic-Wert auf. VMDK-Sparse-Magic (0x564D444B) verwendet vmdkDescriptorReadSparse und behält die bereits geöffnete Datei als Extent. ASCII verwendet vmdkDescriptorReadAscii und den obigen Join.