113 lines
2.9 KiB
Ruby
113 lines
2.9 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
include Msf::Auxiliary::Report
|
|
include Msf::Auxiliary::UDPScanner
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Ubiquiti Discovery Scanner',
|
|
'Description' => 'Detects Ubiquiti devices using a UDP discovery service',
|
|
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
|
|
'License' => MSF_LICENSE,
|
|
'References' =>
|
|
[
|
|
['URL', 'https://www.cisa.gov/uscert/ncas/alerts/TA14-017A'],
|
|
['URL', 'https://community.ubnt.com/t5/airMAX-General-Discussion/airOS-airMAX-and-management-access/td-p/2654023'],
|
|
['URL', 'https://www.rapid7.com/blog/post/2019/02/01/ubiquiti-discovery-service-exposures/']
|
|
]
|
|
)
|
|
)
|
|
|
|
register_options([
|
|
Opt::RPORT(10001)
|
|
])
|
|
end
|
|
|
|
def build_probe
|
|
@probe = "\x01\x00\x00\x00"
|
|
end
|
|
|
|
def scanner_process(data, shost, sport)
|
|
offset = 0
|
|
if data.length < 4
|
|
return
|
|
end
|
|
|
|
type, length = data.unpack("vn")
|
|
offset += 4
|
|
if type != 1 || length != data.length - offset
|
|
return
|
|
end
|
|
|
|
remaining = data.length - offset
|
|
info = {'ips' => [], 'macs' => []}
|
|
while remaining > 0
|
|
type, length = data.slice(offset, 3).unpack("Cn")
|
|
offset += 3
|
|
remaining -= 4
|
|
|
|
field_data = data.slice(offset, length)
|
|
offset += length
|
|
remaining -= length
|
|
if field_data.empty?
|
|
next
|
|
end
|
|
# name
|
|
case type
|
|
when 0x0b
|
|
info['name'] = field_data
|
|
# MAC
|
|
when 0x01
|
|
info['macs'] << field_data.each_byte.map { |b| b.to_s(16) }.join(':')
|
|
# MAC and IP
|
|
when 0x02
|
|
info['macs'] << field_data.slice(0,6).each_byte.map { |b| b.to_s(16) }.join(':')
|
|
info['ips'] << field_data.slice(6,4).each_byte.map { |b| b.to_i }.join('.')
|
|
# long model
|
|
when 0x14
|
|
info['model_long'] = field_data
|
|
# short model
|
|
when 0x0c
|
|
info['model_short'] = field_data
|
|
# firmware version
|
|
when 0x03
|
|
info['firmware'] = field_data
|
|
# essid in some situations
|
|
when 0x0d
|
|
info['essid'] = field_data
|
|
else
|
|
vprint_warning("#{shost}:#{sport} skipping unhandled #{length}-byte field type '#{type}': '#{field_data.unpack("H*")}'")
|
|
end
|
|
end
|
|
|
|
if ! info['macs'].any?
|
|
info.delete('macs')
|
|
end
|
|
info['macs'] = info['macs'].sort.uniq
|
|
|
|
if ! info['ips'].any?
|
|
info.delete('ips')
|
|
end
|
|
info['ips'] = info['ips'].sort.uniq
|
|
|
|
if info.empty?
|
|
return
|
|
end
|
|
|
|
print_good("#{shost}:#{sport} Ubiquiti Discovery metadata: #{info}")
|
|
report_service(
|
|
host: shost,
|
|
proto: 'udp',
|
|
port: rport,
|
|
info: info,
|
|
name: 'ubiquiti_discovery'
|
|
)
|
|
end
|
|
end
|