Skip to content

Commit 7791c58

Browse files
committed
rubocop check & msftidy run clean. Minor updates.
1 parent 1600879 commit 7791c58

File tree

2 files changed

+58
-96
lines changed

2 files changed

+58
-96
lines changed

documentation/modules/auxiliary/scanner/http/epmp1000_web_login.md

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ This module scans for Cambium ePMP 1000 management login portal(s), and attempts
22

33
## Verification Steps
44

5-
1. Do: ```auxiliary/scanner/http/epmp1000_web_login```
5+
1. Do: ```use auxiliary/scanner/http/epmp1000_web_login```
66
2. Do: ```set RHOSTS [IP]```
77
3. Do: ```set RPORT [PORT]```
88
4. Do: ```run```
@@ -11,45 +11,6 @@ This module scans for Cambium ePMP 1000 management login portal(s), and attempts
1111

1212
```
1313
msf > use auxiliary/scanner/http/epmp1000_web_login
14-
msf auxiliary(epmp1000_web_login) > info
15-
16-
Name: Cambium ePMP 1000 Login Scanner
17-
Module: auxiliary/scanner/http/epmp1000_web_login
18-
License: Metasploit Framework License (BSD)
19-
Rank: Normal
20-
21-
Provided by:
22-
Karn Ganeshen <[email protected]>
23-
24-
Basic options:
25-
Name Current Setting Required Description
26-
---- --------------- -------- -----------
27-
BLANK_PASSWORDS false no Try blank passwords for all users
28-
BRUTEFORCE_SPEED 5 yes How fast to bruteforce, from 0 to 5
29-
DB_ALL_CREDS false no Try each user/password couple stored in the current database
30-
DB_ALL_PASS false no Add all passwords in the current database to the list
31-
DB_ALL_USERS false no Add all users in the current database to the list
32-
PASSWORD admin no A specific password to authenticate with
33-
PASS_FILE no File containing passwords, one per line
34-
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
35-
RHOSTS yes The target address range or CIDR identifier
36-
RPORT 80 yes The target port
37-
SSL false no Negotiate SSL/TLS for outgoing connections
38-
STOP_ON_SUCCESS false yes Stop guessing when a credential works for a host
39-
THREADS 1 yes The number of concurrent threads
40-
USERNAME admin no A specific username to authenticate as
41-
USERPASS_FILE no File containing users and passwords separated by space, one pair per line
42-
USER_AS_PASS false no Try the username as the password for all users
43-
USER_FILE no File containing usernames, one per line
44-
VERBOSE true yes Whether to print output for all attempts
45-
VHOST no HTTP server virtual host
46-
47-
Description:
48-
This module scans for Cambium ePMP 1000 management login portal(s),
49-
and attempts to identify valid credentials. Default login
50-
credentials are - admin/admin, installer/installer, home/home and
51-
readonly/readonly.
52-
5314
msf auxiliary(epmp1000_web_login) > set rhosts 1.2.3.4
5415
msf auxiliary(epmp1000_web_login) > set username installer
5516
msf auxiliary(epmp1000_web_login) > set password installer

modules/auxiliary/scanner/http/epmp1000_web_login.rb

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,23 @@ def initialize(info={})
1515
super(update_info(info,
1616
'Name' => 'Cambium ePMP 1000 Login Scanner',
1717
'Description' => %{
18-
This module scans for Cambium ePMP 1000 management login portal(s), and attempts to identify valid credentials. Default login credentials are - admin/admin, installer/installer, home/home and readonly/readonly.
18+
This module scans for Cambium ePMP 1000 management login portal(s), and attempts to identify valid credentials. Default login credentials are - admin/admin, installer/installer, home/home and readonly/readonly. Tested versions <=3.2.1 (current version). This should work fine for any future releases.
1919
},
2020
'Author' =>
2121
[
22-
'Karn Ganeshen <KarnGaneshen[at]gmail.com>',
22+
'Karn Ganeshen <KarnGaneshen[at]gmail.com>'
2323
],
2424
'License' => MSF_LICENSE,
25-
'DefaultOptions' => { 'VERBOSE' => true }
26-
))
25+
'DefaultOptions' => { 'VERBOSE' => true })
26+
)
2727

2828
register_options(
29-
[
30-
Opt::RPORT(80), # Application may run on a different port too. Change port accordingly.
31-
OptString.new('USERNAME', [false, "A specific username to authenticate as", "admin"]),
32-
OptString.new('PASSWORD', [false, "A specific password to authenticate with", "admin"])
33-
], self.class)
29+
[
30+
Opt::RPORT(80), # Application may run on a different port too. Change port accordingly.
31+
OptString.new('USERNAME', [false, 'A specific username to authenticate as', 'admin']),
32+
OptString.new('PASSWORD', [false, 'A specific password to authenticate with', 'admin'])
33+
], self.class
34+
)
3435
end
3536

3637
def run_host(ip)
@@ -78,16 +79,17 @@ def report_cred(opts)
7879
def is_app_epmp1000?
7980
begin
8081
res = send_request_cgi(
81-
{
82-
'uri' => '/',
83-
'method' => 'GET'
84-
})
82+
{
83+
'uri' => '/',
84+
'method' => 'GET'
85+
}
86+
)
8587
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError
8688
print_error("#{rhost}:#{rport} - HTTP Connection Failed...")
8789
return false
8890
end
8991

90-
if (res and res.code == 200 and res.headers['Server'] and (res.headers['Server'].include?("Cambium HTTP Server") or res.body.include?("cambiumnetworks.com")))
92+
if (res && res.code == 200 && res.headers['Server'] && (res.headers['Server'].include?('Cambium HTTP Server') || res.body.include?('cambiumnetworks.com')))
9193

9294
get_epmp_ver = res.body.match(/"sw_version">([^<]*)/)
9395
epmp_ver = get_epmp_ver[1]
@@ -114,73 +116,72 @@ def do_login(user, pass)
114116
begin
115117

116118
res = send_request_cgi(
117-
{
118-
'uri' => '/cgi-bin/luci',
119-
'method' => 'POST',
120-
'headers' => {'X-Requested-With' => 'XMLHttpRequest','Accept' => 'application/json, text/javascript, */*; q=0.01'},
121-
'vars_post' =>
122-
{
123-
'username' => 'dashboard',
124-
'password' => ''
125-
}
126-
})
127-
128-
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
119+
{
120+
'uri' => '/cgi-bin/luci',
121+
'method' => 'POST',
122+
'headers' => { 'X-Requested-With' => 'XMLHttpRequest', 'Accept' => 'application/json, text/javascript, */*; q=0.01' },
123+
'vars_post' =>
124+
{
125+
'username' => 'dashboard',
126+
'password' => ''
127+
}
128+
}
129+
)
130+
131+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionError, ::Errno::EPIPE
129132

130133
vprint_error("#{rhost}:#{rport} - HTTP Connection Failed...")
131134
return :abort
132135

133136
end
134137

135-
if (res and res.code == 200 and res.headers.include?("Set-Cookie") and res.headers['Set-Cookie'].include?("sysauth"))
138+
if (res && res.code == 200 && res.headers.include?('Set-Cookie') && res.headers['Set-Cookie'].include?('sysauth'))
136139

137140
get_cookie = res.headers['Set-Cookie']
138141
get_stok = res.headers['Set-Cookie'].match(/stok=(.*)/)
139142
stok_value = get_stok[1]
140143
sysauth_value = res.headers['Set-Cookie'].match(/((.*)[$ ])/)
141-
cookie1 = "#{sysauth_value}; "+"globalParams=%7B%22dashboard%22%3A%7B%22refresh_rate%22%3A%225%22%7D%2C%22#{user}%22%3A%7B%22refresh_rate%22%3A%225%22%7D%7D"
144+
cookie1 = "#{sysauth_value}; " + "globalParams=%7B%22dashboard%22%3A%7B%22refresh_rate%22%3A%225%22%7D%2C%22#{user}%22%3A%7B%22refresh_rate%22%3A%225%22%7D%7D"
142145

143146
res = send_request_cgi(
144-
{
145-
'uri' => '/cgi-bin/luci',
146-
'method' => 'POST',
147-
'cookie' => cookie1,
148-
'headers' => {
149-
'X-Requested-With' => 'XMLHttpRequest',
150-
'Accept' => 'application/json, text/javascript, */*; q=0.01',
151-
'Connection' => 'close'
152-
},
153-
'vars_post' =>
154-
{
155-
'username' => user,
156-
'password' => pass
157-
}
158-
})
147+
{
148+
'uri' => '/cgi-bin/luci',
149+
'method' => 'POST',
150+
'cookie' => cookie1,
151+
'headers' => { 'X-Requested-With' => 'XMLHttpRequest', 'Accept' => 'application/json, text/javascript, */*; q=0.01', 'Connection' => 'close' },
152+
'vars_post' =>
153+
{
154+
'username' => user,
155+
'password' => pass
156+
}
157+
}
158+
)
159159

160160
end
161161

162-
if (res and res.code == 200 and res.headers.include?("Set-Cookie") and res.headers['Set-Cookie'].include?("stok="))
162+
if (res && res.code == 200 && res.headers.include?('Set-Cookie') && res.headers['Set-Cookie'].include?('stok='))
163163

164164
print_good("SUCCESSFUL LOGIN - #{rhost}:#{rport} - #{user.inspect}:#{pass.inspect}")
165165

166-
#
167-
# Extract ePMP version
168-
#
166+
#
167+
# Extract ePMP version
168+
#
169169
res = send_request_cgi(
170-
{
171-
'uri' => '/',
172-
'method' => 'GET'
173-
})
170+
{
171+
'uri' => '/',
172+
'method' => 'GET'
173+
}
174+
)
174175

175176
get_epmp_ver = res.body.match(/"sw_version">([^<]*)/)
176177
epmp_ver = get_epmp_ver[1]
177178

178179
report_cred(
179-
ip: rhost,
180-
port: rport,
181-
service_name: "Cambium ePMP 1000 version #{epmp_ver}",
182-
user: user,
183-
password: pass
180+
ip: rhost,
181+
port: rport,
182+
service_name: "Cambium ePMP 1000 version #{epmp_ver}",
183+
user: user,
184+
password: pass
184185
)
185186

186187
else

0 commit comments

Comments
 (0)