remove brocade_telnet scanner, extend telnet

Rather than duplicate the entire telnet scanner, add a pre-login hook that a
module can use to extend the behavior on connect. This also adds a local
pass-through print_error method like http has.
bug/bundler_fix
Brent Cook 2015-05-01 17:41:08 -05:00
parent dc053aeb58
commit 93c785560b
3 changed files with 39 additions and 143 deletions

View File

@ -1,122 +0,0 @@
require 'msf/core'
require 'metasploit/framework/telnet/client'
require 'metasploit/framework/login_scanner/base'
require 'metasploit/framework/login_scanner/rex_socket'
module Metasploit
module Framework
module LoginScanner
# This is based off of the telnet LoginScanner. We had to role our own,
# based on hdm's recommendation, since we're not trying to login to telnet,
# but we're actually doing the escalated privileges (enable) login.
class Brocade_Telnet
include Metasploit::Framework::LoginScanner::Base
include Metasploit::Framework::LoginScanner::RexSocket
include Metasploit::Framework::Telnet::Client
CAN_GET_SESSION = true
DEFAULT_PORT = 23
LIKELY_PORTS = [ DEFAULT_PORT ]
LIKELY_SERVICE_NAMES = [ 'telnet' ]
PRIVATE_TYPES = [ :password ]
REALM_KEY = nil
# @!attribute verbosity
# The timeout to wait for the telnet banner.
#
# @return [Fixnum]
attr_accessor :banner_timeout
# @!attribute verbosity
# The timeout to wait for the response from a telnet command.
#
# @return [Fixnum]
attr_accessor :telnet_timeout
validates :banner_timeout,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 1
}
validates :telnet_timeout,
presence: true,
numericality: {
only_integer: true,
greater_than_or_equal_to: 1
}
# (see {Base#attempt_login})
def attempt_login(credential)
result_options = {
credential: credential,
host: host,
port: port,
protocol: 'tcp',
service_name: 'telnet'
}
begin
if connect_reset_safe == :refused
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
else
if busy_message?
self.sock.close unless self.sock.closed?
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
end
end
unless result_options[:status]
raw_send("enable\r\n") #send the enable command
unless password_prompt?
send_user(credential.public)
end
recvd_sample = @recvd.dup
# Allow for slow echos
1.upto(10) do
recv_telnet(self.sock, 0.10) unless @recvd.nil? or @recvd[/#{@password_prompt}/]
end
if password_prompt?(credential.public)
send_pass(credential.private)
# Allow for slow echos
1.upto(10) do
recv_telnet(self.sock, 0.10) if @recvd == recvd_sample
end
end
if login_succeeded?
result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL
else
result_options[:status] = Metasploit::Model::Login::Status::INCORRECT
end
end
rescue ::EOFError, Errno::ECONNRESET, Rex::ConnectionError, Rex::ConnectionTimeout, ::Timeout::Error
result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
end
::Metasploit::Framework::LoginScanner::Result.new(result_options)
end
private
# This method sets the sane defaults for things
# like timeouts and TCP evasion options
def set_sane_defaults
self.connection_timeout ||= 30
self.port ||= DEFAULT_PORT
self.banner_timeout ||= 25
self.telnet_timeout ||= 10
self.connection_timeout ||= 30
self.max_send_size ||= 0
self.send_delay ||= 0
# Shim to set up the ivars from the old Login mixin
create_login_ivars
end
end
end
end
end

View File

@ -30,6 +30,11 @@ module Metasploit
# #
# @return [Fixnum] # @return [Fixnum]
attr_accessor :telnet_timeout attr_accessor :telnet_timeout
# @!attribute verbosity
# Prepend code to call before checking for a user login
#
# @return [Proc]
attr_accessor :pre_login
validates :banner_timeout, validates :banner_timeout,
presence: true, presence: true,
@ -66,6 +71,10 @@ module Metasploit
end end
unless result_options[:status] unless result_options[:status]
if pre_login
pre_login.call(self)
end
unless password_prompt? unless password_prompt?
send_user(credential.public) send_user(credential.public)
end end
@ -108,6 +117,7 @@ module Metasploit
self.port ||= DEFAULT_PORT self.port ||= DEFAULT_PORT
self.banner_timeout ||= 25 self.banner_timeout ||= 25
self.telnet_timeout ||= 10 self.telnet_timeout ||= 10
self.pre_login ||= nil
self.connection_timeout ||= 30 self.connection_timeout ||= 30
self.max_send_size ||= 0 self.max_send_size ||= 0
self.send_delay ||= 0 self.send_delay ||= 0
@ -115,6 +125,10 @@ module Metasploit
create_login_ivars create_login_ivars
end end
def print_error( message )
return if !@parent
@parent.print_error message
end
end end
end end
end end

View File

@ -6,7 +6,7 @@
require 'msf/core' require 'msf/core'
require 'rex' require 'rex'
require 'metasploit/framework/credential_collection' require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/brocade_telnet' require 'metasploit/framework/login_scanner/telnet'
class Metasploit4 < Msf::Auxiliary class Metasploit4 < Msf::Auxiliary
@ -20,16 +20,14 @@ class Metasploit4 < Msf::Auxiliary
super( super(
'Name' => 'Brocade Enable Login Check Scanner', 'Name' => 'Brocade Enable Login Check Scanner',
'Description' => %q{ 'Description' => %q{
This module will test a Brocade network device for a privilged This module will test a range of Brocade network devices for a
(Enable) login on a range of machines and report successful privileged logins and report successes. The device authentication mode
logins. If you have loaded a database plugin and connected must be set as 'aaa authentication enable default local'.
to a database this module will record successful Telnet authentication, e.g. 'enable telnet authentication', should not
logins and hosts so you can track your access. be enabled in the device configuration.
This is not a login/telnet authentication. Config should NOT
have 'enable telnet authentication' in it. This will test the This module has been tested against the following devices:
config that contains 'aaa authentication enable default local' ICX6450-24 SWver 07.4.00bT311,
Tested against:
ICX6450-24 SWver 07.4.00bT311
FastIron WS 624 SWver 07.2.02fT7e1 FastIron WS 624 SWver 07.2.02fT7e1
}, },
'Author' => 'h00die <mike[at]shorebreaksecurity.com>', 'Author' => 'h00die <mike[at]shorebreaksecurity.com>',
@ -48,25 +46,29 @@ class Metasploit4 < Msf::Auxiliary
end end
def get_username_from_config(un_list,ip) def get_username_from_config(un_list,ip)
["config","running-config"].each do |command| ["config", "running-config"].each do |command|
print_status(" Attempting username gathering from #{command} on #{ip}") print_status(" Attempting username gathering from #{command} on #{ip}")
sock.puts("\r\n") #ensure the buffer is clear sock.puts("\r\n") # ensure that the buffer is clear
config = sock.recv(1024) config = sock.recv(1024)
sock.puts("show #{command}\r\n") sock.puts("show #{command}\r\n")
# pull the entire config
while true do while true do
sock.puts(" \r\n") #paging sock.puts(" \r\n") # paging
config << sock.recv(1024) config << sock.recv(1024)
#there seems to be some buffering issues. so we want to match that we're back at a prompt, as well as received the 'end' of the config. # Read until we are back at a prompt and have received the 'end' of
# the config.
break if config.match(/>$/) and config.match(/end/) break if config.match(/>$/) and config.match(/end/)
end #pull the entire config end
config.each_line do |un| config.each_line do |un|
if un.match(/^username/) if un.match(/^username/)
found_username = un.split(" ")[1].strip found_username = un.split(" ")[1].strip
un_list.push(found_username) un_list.push(found_username)
print_status(" Found: #{found_username}@#{ip}") print_status(" Found: #{found_username}@#{ip}")
end #username match end
end #each line in config end
end #end config/running-config loop end
end end
attr_accessor :no_pass_prompt attr_accessor :no_pass_prompt
@ -99,7 +101,7 @@ class Metasploit4 < Msf::Auxiliary
cred_collection = prepend_db_passwords(cred_collection) cred_collection = prepend_db_passwords(cred_collection)
scanner = Metasploit::Framework::LoginScanner::Brocade_Telnet.new( scanner = Metasploit::Framework::LoginScanner::Telnet.new(
host: ip, host: ip,
port: rport, port: rport,
proxies: datastore['PROXIES'], proxies: datastore['PROXIES'],
@ -111,6 +113,7 @@ class Metasploit4 < Msf::Auxiliary
send_delay: datastore['TCP::send_delay'], send_delay: datastore['TCP::send_delay'],
banner_timeout: datastore['TelnetBannerTimeout'], banner_timeout: datastore['TelnetBannerTimeout'],
telnet_timeout: datastore['TelnetTimeout'], telnet_timeout: datastore['TelnetTimeout'],
pre_login: lambda{ |s| raw_send("enable\r\n", nsock = s.sock) },
framework: framework, framework: framework,
framework_module: self, framework_module: self,
) )
@ -121,6 +124,7 @@ class Metasploit4 < Msf::Auxiliary
module_fullname: self.fullname, module_fullname: self.fullname,
workspace_id: myworkspace_id workspace_id: myworkspace_id
) )
if result.success? if result.success?
credential_core = create_credential(credential_data) credential_core = create_credential(credential_data)
credential_data[:core] = credential_core credential_data[:core] = credential_core
@ -132,7 +136,7 @@ class Metasploit4 < Msf::Auxiliary
print_error("#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})") print_error("#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})")
end end
end end
end #end un loop end
end end
def start_telnet_session(host, port, user, pass, scanner) def start_telnet_session(host, port, user, pass, scanner)