
Oracle VM VirtualBox 7.2.20 - Alta - Local - Leitura de arquivo - Junção de caminho de extensão FLAT esparsa VMDK
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · vbox-vmdk-sparse-extent
Classe: Leitura de arquivo Alcance: Local (host) UI:R
Oracle VM VirtualBox OSS 7.2.20 (f2792cf44) - Oracle
Um usuário do host que importa um diretório OVF ou OVA cujo disco é um descritor VMDK esparso mais uma extensão FLAT abre um caminho do host nomeado nessa extensão e copia esses bytes para o disco importado. Após vmdkParseDescriptor, cada extensão com pszBasename começando com RTPATH_SLASH é usada como está; caso contrário, RTPathJoinA(descriptor dir, pszBasename) que segue ../. FLAT e HOSTED_SPARSE então fazem vmdkFileOpen nesse caminho completo. streamOptimized (exportação usual do VirtualBox, magic VMDK) é um único arquivo e não percorre esse caminho. A importação ainda aceita o especificador esparso.
| ID | ainda sem CVE |
| Classe | Leitura de arquivo (caminho de extensão FLAT/esparsa de VMDK esparso) |
| Alcance | Local (host) UI:R (a vítima importa um appliance hostil) |
| CWE | CWE-22 |
| CVSS | Alto: 7.7 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N |
| Produto | Oracle VM VirtualBox OSS |
| Afetado | 7.2.20 (f2792cf44f663989818507e36d3db5f978523c5e) |
| Autenticação | nenhuma no VirtualBox. O usuário do host abre Arquivo/Importar ou VBoxManage import. |
| Licença | GNU Affero GPL v3.0 |
| Laboratório | apenas 127.0.0.1. Harness de código-fonte. O VirtualBox não é inicializado. |
Entregue um diretório OVF ou um OVA. Coloque um descritor VMDK esparso (# Disk DescriptorFile, createType="monolithicFlat") ao lado de uma extensão FLAT cujo basename entre aspas seja ../../somewhere/secret ou /path/secret. O operador que o importa abre esse caminho do host com o UID de importação e copia os bytes para o disco de destino. streamOptimized (magic VMDK 0x564D444B) não consulta o nome FLAT embutido. Trata-se de uma leitura de arquivos que o UID do VBox consegue abrir, não de uma escrita sem sufixo em authorized_keys.
| Privilégio | Método + sink | O que concede | Proveniência |
|---|---|---|---|
| Recon | Importação de um VMDK esparso ASCII. Após vmdkParseDescriptor, RTPathJoinA(descriptor dir, pszBasename) sem colapso de ../ (VMDK.cpp 3472-3503). vmdkFileOpen FLAT desse caminho completo. A importação copia esses bytes para o destino. | Bytes de ficheiro do host nomeados por ../ acabam no disco importado. Laboratório: pszBasename ../../oracle/VBOX-VMDK-SPARSE-EXTENT-WITNESS juntado a /work/import/disk/../../oracle/... e copiado para /work/import/out.vmdk. | Provado em laboratório (relative-escape=yes) |
| Recon | Mesma travessia. pszBasename[0] == RTPATH_SLASH é usado tal como está (VMDK.cpp 3477-3485). | Caminho absoluto do host aberto e copiado. Laboratório: /work/oracle/VBOX-VMDK-SPARSE-EXTENT-WITNESS. | Provado em laboratório (absolute-extent=yes) |
| Recon | Controlo FLAT disk-flat.vmdk juntado sob o diretório do descritor. | Permanece dentro da pasta. Laboratório: nome completo /work/import/disk/disk-flat.vmdk. Bytes CONTROL-FLAT-NOT-ORACLE. | Provado em laboratório (control-in-folder=yes) |
| Recon | streamOptimized com magia VMDK. vmdkDescriptorRead usa vmdkDescriptorReadSparse. FLAT ASCII incorporado nomeava o oracle. | Não abriu o nome incorporado. O destino permaneceu o ficheiro stream (STREAMOPTIMIZED-SELF-NOT-ORACLE). | Provado em laboratório (streamoptimized-consults-extent=no) |
| Recon | Arranque do guest e, em seguida, leitura do volume convertido. | O guest vê conteúdos de ficheiros do host legíveis pelo UID do importador que acabaram no destino. | Inferido (mesma cópia; o laboratório não arranca um guest) |
| Disponibilidade | Destino de importação que já existe, ou uma montagem posterior do disco convertido. | Disponibilidade de sobrescrita do disco de destino. Os conteúdos tornam-se o ficheiro do host aberto. | Inferido (mesma escrita no destino) |
| Fechado | VMDK streamOptimized (exportação habitual do VirtualBox) | Ramo da magia. Ficheiro único. O nome FLAT incorporado não é aberto. | Fechado |
| Fechado | Letra de unidade absoluta do Windows (C:\...) | Pode falhar pszBasename[0] == RTPATH_SLASH. O código chama à verificação absoluta um hack (@todo implement proper path absolute check). | Fechado |
| Fechado | Escritas sem sufixo (authorized_keys, crontab) | Não é um resíduo de escrita. A abertura do extent é uma leitura do caminho do host nomeado. | Fechado |
| Fechado | Kernel do host, guest-para-host, outras VMs, memória do VBoxSVC | Não é este resíduo. Não é necessário arrancar uma VM para a cópia. Mesmo UID que o importador. | Fechado |
OVA é a mesma travessia assim que o descritor esparso está em disco: o membro tar fornece o descritor mais (opcionalmente) o FLAT dentro da pasta; o basename do extent fornece a abertura escapada. Sem 3D, sem Guest Additions, sem VRDP, não é PUEL.
Fiquei na tag v7.2.20 (f2792cf44) após a CPU de setembro de 2026 e li a importação de VMDK. ExtraData, pastas partilhadas, destino NVRAM e RawFile de série já estão removidos. O destino ovf:href é um resíduo irmão. A exportação habitual do VirtualBox é streamOptimized. interpret() ainda aceita o especificador esparso (g_pszVMDKSparseURI). Após vmdkParseDescriptor, o basename do extent é juntado sem colapsar ../ nem rejeitar caminhos absolutos:
/* 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 apenas equilibra barras. Não colapsa ... FLAT e HOSTED_SPARSE então abrem essa string:
case VMDKETYPE_FLAT:
rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */));
vmdkDescriptorRead divide pelo magic. O magic de VMDK esparso (0x564D444B) usa vmdkDescriptorReadSparse e mantém o arquivo já aberto como a extensão. ASCII usa vmdkDescriptorReadAscii e a junção acima.
Caminhos errados já registrados: tratar streamOptimized como este resíduo (o magic não consulta o nome FLAT embutido); tratar um caminho absoluto com letra de unidade do Windows como a verificação de barra do Unix; tratar a sobrescrita do disco de destino como uma escrita de authorized_keys sem sufixo; inicializar uma VM quando o harness de origem da junção é suficiente. Teatro: kernel do host, convidado-para-host. O oráculo é uma linha testemunha fora da pasta do descritor mais um disk-flat.vmdk de controle que permaneceu no lugar.
python3 vbox-vmdk-sparse-extent-Abraxas-Labs.py
ou