2014-07-18 00:17:31 +00:00
|
|
|
# encoding: UTF-8
|
2009-03-29 05:51:08 +00:00
|
|
|
##
|
2013-10-15 18:50:46 +00:00
|
|
|
# This module requires Metasploit: http//metasploit.com/download
|
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2009-03-29 05:51:08 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
2014-07-18 00:17:31 +00:00
|
|
|
require 'rex/proto/sip'
|
2009-03-29 05:51:08 +00:00
|
|
|
|
|
|
|
class Metasploit3 < Msf::Auxiliary
|
2013-08-30 21:28:54 +00:00
|
|
|
include Msf::Auxiliary::Report
|
|
|
|
include Msf::Auxiliary::Scanner
|
2014-07-18 00:17:31 +00:00
|
|
|
include Rex::Proto::SIP
|
2013-08-30 21:28:54 +00:00
|
|
|
|
|
|
|
def initialize
|
|
|
|
super(
|
|
|
|
'Name' => 'SIP Endpoint Scanner (UDP)',
|
|
|
|
'Description' => 'Scan for SIP devices using OPTIONS requests',
|
|
|
|
'Author' => 'hdm',
|
|
|
|
'License' => MSF_LICENSE
|
|
|
|
)
|
|
|
|
|
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
OptInt.new('BATCHSIZE', [true, 'The number of hosts to probe in each set', 256]),
|
2014-07-18 00:17:31 +00:00
|
|
|
OptString.new('TO', [false, 'The destination username to probe at each host', 'nobody']),
|
2013-08-30 21:28:54 +00:00
|
|
|
Opt::RPORT(5060),
|
|
|
|
Opt::CHOST,
|
|
|
|
Opt::CPORT(5060)
|
|
|
|
], self.class)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Define our batch size
|
|
|
|
def run_batch_size
|
|
|
|
datastore['BATCHSIZE'].to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
# Operate on an entire batch of hosts at once
|
|
|
|
def run_batch(batch)
|
2014-07-18 00:17:31 +00:00
|
|
|
udp_sock = nil
|
|
|
|
idx = 0
|
|
|
|
# Create an unbound UDP socket if no CHOST is specified, otherwise
|
|
|
|
# create a UDP socket bound to CHOST (in order to avail of pivoting)
|
|
|
|
udp_sock = Rex::Socket::Udp.create(
|
|
|
|
'LocalHost' => datastore['CHOST'] || nil,
|
|
|
|
'LocalPort' => datastore['CPORT'].to_i,
|
|
|
|
'Context' => { 'Msf' => framework, 'MsfExploit' => self }
|
|
|
|
)
|
|
|
|
add_socket(udp_sock)
|
|
|
|
batch.each do |ip|
|
|
|
|
data = create_probe(ip, 'UDP')
|
|
|
|
begin
|
|
|
|
udp_sock.sendto(data, ip, datastore['RPORT'].to_i, 0)
|
|
|
|
rescue ::Interrupt
|
|
|
|
raise $ERROR_INFO
|
|
|
|
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
|
|
|
|
nil
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
2014-07-18 00:17:31 +00:00
|
|
|
handle_replies(udp_sock) if idx % 10 == 0
|
|
|
|
idx += 1
|
|
|
|
end
|
2013-08-30 21:28:54 +00:00
|
|
|
|
2014-07-18 00:17:31 +00:00
|
|
|
begin
|
|
|
|
handle_replies(udp_sock)
|
2013-08-30 21:28:54 +00:00
|
|
|
rescue ::Interrupt
|
2014-07-18 00:17:31 +00:00
|
|
|
raise $ERROR_INFO
|
|
|
|
rescue => e
|
2013-08-30 21:28:54 +00:00
|
|
|
print_error("Unknown error: #{e.class} #{e}")
|
|
|
|
ensure
|
|
|
|
udp_sock.close if udp_sock
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-07-18 00:17:31 +00:00
|
|
|
def handle_replies(udp_sock)
|
|
|
|
r = read_reply(udp_sock)
|
|
|
|
while r && r[1]
|
|
|
|
handle_reply(r)
|
|
|
|
r = read_reply(udp_sock)
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-07-18 00:17:31 +00:00
|
|
|
def read_reply(udp_sock)
|
|
|
|
udp_sock.recvfrom(65535, 0.01)
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
2010-04-30 08:40:19 +00:00
|
|
|
|
2014-07-18 00:17:31 +00:00
|
|
|
def handle_reply(pkt)
|
|
|
|
return unless pkt[1]
|
|
|
|
|
|
|
|
pkt[1].sub!(/^::ffff:/, '')
|
2009-03-29 05:51:08 +00:00
|
|
|
|
2014-07-18 00:17:31 +00:00
|
|
|
resp = pkt[0].split(/\s+/)[1]
|
2014-07-18 17:29:14 +00:00
|
|
|
parse_response(resp, 'udp')
|
2014-07-18 00:17:31 +00:00
|
|
|
end
|
2009-03-29 05:51:08 +00:00
|
|
|
end
|