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
parent
dc053aeb58
commit
93c785560b
|
@ -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
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue