Don't raise in the middle
MSP-11343 This means we don't bomb out with an unhandled exception, instead continuing attempting logins against the host even though it will never succeed. Next up: verify state before running scan!()bug/bundler_fix
parent
5477d5452e
commit
84e4db9035
|
@ -5,10 +5,6 @@ module Metasploit
|
|||
module Framework
|
||||
module LoginScanner
|
||||
|
||||
# I don't want to raise RuntimeError to be able to abort login
|
||||
class GlassfishError < StandardError
|
||||
end
|
||||
|
||||
# The Glassfish HTTP LoginScanner class provides methods to do login routines
|
||||
# for Glassfish 2, 3 and 4.
|
||||
class Glassfish < HTTP
|
||||
|
@ -24,7 +20,6 @@ module Metasploit
|
|||
# @return [String] Cookie session
|
||||
attr_accessor :jsession
|
||||
|
||||
|
||||
# Sends a HTTP request with Rex
|
||||
#
|
||||
# @param (see Rex::Proto::Http::Resquest#request_raw)
|
||||
|
@ -126,9 +121,9 @@ module Metasploit
|
|||
return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
|
||||
end
|
||||
elsif res && is_secure_admin_disabled?(res)
|
||||
return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
|
||||
return {:status => Metasploit::Model::Login::Status::DENIED_ACCESS, :proof => res.body}
|
||||
elsif res && res.code == 400
|
||||
raise GlassfishError, "400: Bad HTTP request from try_login"
|
||||
return {:status => Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, :proof => res.body}
|
||||
end
|
||||
|
||||
{:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body}
|
||||
|
@ -146,12 +141,10 @@ module Metasploit
|
|||
case self.version
|
||||
when /^[29]\.x$/
|
||||
status = try_glassfish_2(credential)
|
||||
result_opts.merge!(status: status[:status], proof:status[:proof])
|
||||
result_opts.merge!(status)
|
||||
when /^[34]\./
|
||||
status = try_glassfish_3(credential)
|
||||
result_opts.merge!(status: status[:status], proof:status[:proof])
|
||||
else
|
||||
raise GlassfishError, "Glassfish version '#{self.version}' not supported"
|
||||
result_opts.merge!(status)
|
||||
end
|
||||
rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error
|
||||
result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT)
|
||||
|
@ -160,6 +153,29 @@ module Metasploit
|
|||
Result.new(result_opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Extract the target's glassfish version from the HTTP Server header
|
||||
# (ex: Sun Java System Application Server 9.x)
|
||||
#
|
||||
# @param banner [String] `Server` header from a Glassfish service response
|
||||
# @return [String] version string, e.g. '2.x'
|
||||
# @return [nil] If the banner did not match any of the expected values
|
||||
def extract_version(banner)
|
||||
# Set version. Some GlassFish servers return banner "GlassFish v3".
|
||||
if banner =~ /(GlassFish Server|Open Source Edition)[[:blank:]]*(\d\.\d)/
|
||||
@version = $2
|
||||
elsif banner =~ /GlassFish v(\d)/
|
||||
@version = $1
|
||||
elsif banner =~ /Sun GlassFish Enterprise Server v2/
|
||||
@version = '2.x'
|
||||
elsif banner =~ /Sun Java System Application Server 9/
|
||||
@version = '9.x'
|
||||
end
|
||||
|
||||
return @version
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,52 +51,11 @@ class Metasploit3 < Msf::Auxiliary
|
|||
# the LoginScanner class so the authentication can proceed properly
|
||||
#
|
||||
|
||||
def jsession
|
||||
@jsession || ''
|
||||
end
|
||||
|
||||
def set_jsession(res)
|
||||
if res && res.get_cookies =~ /JSESSIONID=(\w*);/i
|
||||
@scanner.jsession = $1
|
||||
end
|
||||
end
|
||||
|
||||
# Overrides the ssl method from HttpClient
|
||||
def ssl
|
||||
@scanner.ssl || datastore['SSL']
|
||||
end
|
||||
|
||||
#
|
||||
# Return GlassFish's edition (Open Source or Commercial) and version (2.x, 3.0, 3.1, 9.x, 4.0) and
|
||||
# banner (ex: Sun Java System Application Server 9.x)
|
||||
#
|
||||
def get_version(res)
|
||||
# Extract banner from response
|
||||
banner = res.headers['Server'] || ''
|
||||
|
||||
# Default value for edition and glassfish version
|
||||
edition = 'Commercial'
|
||||
version = 'Unknown'
|
||||
|
||||
# Set edition (Open Source or Commercial)
|
||||
p = /(Open Source|Sun GlassFish Enterprise Server|Sun Java System Application Server)/
|
||||
edition = 'Open Source' if banner =~ p
|
||||
|
||||
# Set version. Some GlassFish servers return banner "GlassFish v3".
|
||||
if banner =~ /(GlassFish Server|Open Source Edition)[[:blank:]]*(\d\.\d)/
|
||||
version = $2
|
||||
elsif banner =~ /GlassFish v(\d)/ && version.nil?
|
||||
version = $1
|
||||
elsif banner =~ /Sun GlassFish Enterprise Server v2/ && version == 'Unknown'
|
||||
version = '2.x'
|
||||
elsif banner =~ /Sun Java System Application Server 9/ && version == 'Unknown'
|
||||
version = '9.x'
|
||||
end
|
||||
|
||||
return edition, version, banner
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# For a while, older versions of Glassfish didn't need to set a password for admin,
|
||||
# but looks like no longer the case anymore, which means this method is getting useless
|
||||
|
@ -107,14 +66,12 @@ class Metasploit3 < Msf::Auxiliary
|
|||
|
||||
if version =~ /^[29]\.x$/
|
||||
res = send_request_cgi({'uri'=>'/applications/upload.jsf'})
|
||||
set_jsession(res)
|
||||
p = /<title>Deploy Enterprise Applications\/Modules/
|
||||
if (res && res.code.to_i == 200 && res.body.match(p) != nil)
|
||||
success = true
|
||||
end
|
||||
elsif version =~ /^3\./
|
||||
res = send_request_cgi({'uri'=>'/common/applications/uploadFrame.jsf'})
|
||||
set_jsession(res)
|
||||
p = /<title>Deploy Applications or Modules/
|
||||
if (res && res.code.to_i == 200 && res.body.match(p) != nil)
|
||||
success = true
|
||||
|
@ -185,6 +142,10 @@ class Metasploit3 < Msf::Auxiliary
|
|||
print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}'"
|
||||
do_report(ip, rport, result)
|
||||
:next_user
|
||||
when Metasploit::Model::Login::Status::DENIED_ACCESS
|
||||
print_brute :level => :status, :ip => ip, :msg => "Correct credentials, but unable to login: '#{result.credential}'"
|
||||
do_report(ip, rport, result)
|
||||
:next_user
|
||||
when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
|
||||
print_brute :level => :verror, :ip => ip, :msg => "Could not connect"
|
||||
invalidate_login(
|
||||
|
@ -220,21 +181,20 @@ class Metasploit3 < Msf::Auxiliary
|
|||
tried = false
|
||||
|
||||
begin
|
||||
print_status("Sending a request to /common/index.jsf...")
|
||||
print_brute :level=>:status, :ip=>rhost, :msg=>"Sending a request to /common/index.jsf..."
|
||||
res = send_request_cgi({'uri'=>'/common/index.jsf'})
|
||||
set_jsession(res)
|
||||
|
||||
# Abort if res returns nil due to an exception (broken pipe or timeout)
|
||||
if res.nil?
|
||||
print_error('Unable to get a response from the server.')
|
||||
print_brute :level=>:error, :ip=>rhost, :msg=>'Unable to get a response from the server.'
|
||||
return
|
||||
end
|
||||
|
||||
# Automatic HTTP to HTTPS transition (when needed)
|
||||
if @scanner.ssl == false && res && res.headers['Location'] =~ /^https:\/\//
|
||||
print_status("Glassfish is asking us to use HTTPS")
|
||||
print_status("SSL option automatically set to: true")
|
||||
print_status("SSL version option automatically set to: #{datastore['SSLVersion']}")
|
||||
print_brute :level=>:status, :ip=>rhost, :msg=>"Glassfish is asking us to use HTTPS"
|
||||
print_brute :level=>:status, :ip=>rhost, :msg=>"SSL option automatically set to: true"
|
||||
print_brute :level=>:status, :ip=>rhost, :msg=>"SSL version option automatically set to: #{datastore['SSLVersion']}"
|
||||
@scanner.ssl = true
|
||||
@scanner.ssl_version = datastore['SSLVersion']
|
||||
# Set the SSL options, and let the exception handler to resend the HTTP request
|
||||
|
@ -255,7 +215,6 @@ class Metasploit3 < Msf::Auxiliary
|
|||
# A normal client starts with /login.jsf, so we start with /login.jsf
|
||||
if res && res.code.to_i == 302
|
||||
res = send_request_cgi({'uri' => '/login.jsf'})
|
||||
set_jsession(res)
|
||||
end
|
||||
|
||||
res
|
||||
|
@ -268,21 +227,17 @@ class Metasploit3 < Msf::Auxiliary
|
|||
def run_host(ip)
|
||||
init_loginscanner(ip)
|
||||
res = init_bruteforce
|
||||
edition, version, banner = get_version(res)
|
||||
@scanner.version = version
|
||||
return if res.nil?
|
||||
@scanner.extract_version(res.headers['Server'])
|
||||
|
||||
print_status('Checking if Glassfish requires a password...')
|
||||
if version =~ /^[239]\.x$/ && is_password_required?(version)
|
||||
print_brute :level=>:status, :ip=>rhost, :msg=>('Checking if Glassfish requires a password...')
|
||||
if @scanner.version =~ /^[239]\.x$/ && is_password_required?(@scanner.version)
|
||||
print_brute :level => :good, :ip => ip, :msg => "Note: This Glassfish does not require a password"
|
||||
else
|
||||
print_status("Glassfish is protected with a password")
|
||||
print_brute :level=>:status, :ip=>rhost, :msg=>("Glassfish is protected with a password")
|
||||
end
|
||||
|
||||
begin
|
||||
bruteforce(ip) unless version.blank?
|
||||
rescue ::Metasploit::Framework::LoginScanner::GlassfishError => e
|
||||
print_error(e.message)
|
||||
end
|
||||
bruteforce(ip) unless @scanner.version.blank?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue