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]
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,
presence: true,
@ -66,6 +71,10 @@ module Metasploit
end
unless result_options[:status]
if pre_login
pre_login.call(self)
end
unless password_prompt?
send_user(credential.public)
end
@ -108,6 +117,7 @@ module Metasploit
self.port ||= DEFAULT_PORT
self.banner_timeout ||= 25
self.telnet_timeout ||= 10
self.pre_login ||= nil
self.connection_timeout ||= 30
self.max_send_size ||= 0
self.send_delay ||= 0
@ -115,6 +125,10 @@ module Metasploit
create_login_ivars
end
def print_error( message )
return if !@parent
@parent.print_error message
end
end
end
end

View File

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