diff --git a/lib/metasploit/framework/login_scanner/advantech_webaccess.rb b/lib/metasploit/framework/login_scanner/advantech_webaccess.rb index 48337496ccc1c..1ee7773da2482 100644 --- a/lib/metasploit/framework/login_scanner/advantech_webaccess.rb +++ b/lib/metasploit/framework/login_scanner/advantech_webaccess.rb @@ -24,6 +24,7 @@ def check_setup }) if res && res.body =~ /Welcome to Advantech WebAccess/i + report_service(service_opts) return false end @@ -67,9 +68,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -82,6 +81,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('advantech_webaccess') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/axis2.rb b/lib/metasploit/framework/login_scanner/axis2.rb index 1772f76adedf3..6c7e301e0651f 100644 --- a/lib/metasploit/framework/login_scanner/axis2.rb +++ b/lib/metasploit/framework/login_scanner/axis2.rb @@ -18,15 +18,8 @@ class Axis2 < HTTP def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end begin # Refactor to access Metasploit::Framework::LoginScanner::HTTP#send_request() @@ -69,6 +62,10 @@ def method=(_) raise RuntimeError, "Method must be POST for Axis2" end + def service_opts + build_service_opts('axis2') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/base.rb b/lib/metasploit/framework/login_scanner/base.rb index 5e42052d6ccf3..587cf1cf93823 100644 --- a/lib/metasploit/framework/login_scanner/base.rb +++ b/lib/metasploit/framework/login_scanner/base.rb @@ -140,6 +140,10 @@ def sleep_between_attempts(time=self.sleep_time) ::IO.select(nil,nil,nil,time) unless sleep_time.zero? end + def workspace + framework_module&.workspace || framework&.db&.workspace&.name + end + def each_credential cred_details.each do |raw_cred| diff --git a/lib/metasploit/framework/login_scanner/bavision_cameras.rb b/lib/metasploit/framework/login_scanner/bavision_cameras.rb index b0d00b290590c..11c1124092941 100644 --- a/lib/metasploit/framework/login_scanner/bavision_cameras.rb +++ b/lib/metasploit/framework/login_scanner/bavision_cameras.rb @@ -25,6 +25,8 @@ def check_setup return "Unable to locate \"realm=IPCamera Login\" in headers. (Is this really a BAVision camera?)" end + report_service(service_opts) + false end @@ -105,9 +107,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -120,6 +120,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('bavision_cameras') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/buffalo.rb b/lib/metasploit/framework/login_scanner/buffalo.rb index b1f97c7e4ff92..fa4f11a651a9b 100644 --- a/lib/metasploit/framework/login_scanner/buffalo.rb +++ b/lib/metasploit/framework/login_scanner/buffalo.rb @@ -24,15 +24,8 @@ def set_sane_defaults def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end begin res = send_request({ 'method'=>'POST', @@ -57,6 +50,10 @@ def attempt_login(credential) end Result.new(result_opts) end + + def service_opts + build_service_opts('buffalo') + end end end end diff --git a/lib/metasploit/framework/login_scanner/caidao.rb b/lib/metasploit/framework/login_scanner/caidao.rb index f6cbae95b30c6..1774740b02588 100644 --- a/lib/metasploit/framework/login_scanner/caidao.rb +++ b/lib/metasploit/framework/login_scanner/caidao.rb @@ -82,17 +82,9 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end - begin result_opts.merge!(try_login(credential.public, credential.private)) rescue ::Rex::ConnectionError => e @@ -100,6 +92,10 @@ def attempt_login(credential) end Result.new(result_opts) end + + def service_opts + build_service_opts('caidao') + end end end end diff --git a/lib/metasploit/framework/login_scanner/chef_webui.rb b/lib/metasploit/framework/login_scanner/chef_webui.rb index 2bc36ed14eaa6..91d3787e21a53 100644 --- a/lib/metasploit/framework/login_scanner/chef_webui.rb +++ b/lib/metasploit/framework/login_scanner/chef_webui.rb @@ -28,9 +28,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -63,6 +61,8 @@ def check_setup return "Unable to connect to target" end + report_service(service_opts) + false end @@ -144,6 +144,10 @@ def try_login(credential) {:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body} end + def service_opts + build_service_opts('chef_webui') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/cisco_firepower.rb b/lib/metasploit/framework/login_scanner/cisco_firepower.rb index 0cb2894469f10..a8e3079a6f5cb 100644 --- a/lib/metasploit/framework/login_scanner/cisco_firepower.rb +++ b/lib/metasploit/framework/login_scanner/cisco_firepower.rb @@ -18,6 +18,7 @@ def check_setup }) if res && res.code == 200 && res.body.include?('/img/favicon.png?v=6.0.1-1213') + report_service(service_opts) return false end @@ -58,9 +59,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -73,6 +72,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('cisco_firepower') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/directadmin.rb b/lib/metasploit/framework/login_scanner/directadmin.rb index a20efc061d3f0..5ceda291fc935 100644 --- a/lib/metasploit/framework/login_scanner/directadmin.rb +++ b/lib/metasploit/framework/login_scanner/directadmin.rb @@ -20,6 +20,7 @@ def check_setup res = send_request({'uri'=> login_uri}) if res && res.body.include?('DirectAdmin Login') + report_service(service_opts) return false end @@ -99,10 +100,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp', - service_name: ssl ? 'https' : 'http' + **service_as_result(service_opts) } begin @@ -115,6 +113,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('directadmin') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/gitlab.rb b/lib/metasploit/framework/login_scanner/gitlab.rb index b260c2fbc8be1..5a0b57378ec60 100644 --- a/lib/metasploit/framework/login_scanner/gitlab.rb +++ b/lib/metasploit/framework/login_scanner/gitlab.rb @@ -21,10 +21,7 @@ def set_sane_defaults def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp', - service_name: ssl ? 'https' : 'http' + **service_as_result(service_opts) } begin # Get a valid session cookie and authenticity_token for the next step @@ -77,6 +74,10 @@ def attempt_login(credential) end Result.new(result_opts) end + + def service_opts + build_service_opts('gitlab') + end end end end diff --git a/lib/metasploit/framework/login_scanner/glassfish.rb b/lib/metasploit/framework/login_scanner/glassfish.rb index 00e673e255736..d167f68111386 100644 --- a/lib/metasploit/framework/login_scanner/glassfish.rb +++ b/lib/metasploit/framework/login_scanner/glassfish.rb @@ -68,6 +68,8 @@ def check_setup return "Unable to connect to target" end + report_service(service_opts) + false end @@ -203,7 +205,10 @@ def try_glassfish_3(credential) # @param credential [Metasploit::Framework::Credential] The credential object # @return [Result] def attempt_login(credential) - result_opts = { credential: credential } + result_opts = { + credential: credential, + **service_as_result(service_opts) + } begin case self.version @@ -248,6 +253,9 @@ def extract_version(banner) return @version end + def service_opts + build_service_opts('glassfish') + end end end diff --git a/lib/metasploit/framework/login_scanner/http.rb b/lib/metasploit/framework/login_scanner/http.rb index 31a9790b01881..8e7f3ae68f35c 100644 --- a/lib/metasploit/framework/login_scanner/http.rb +++ b/lib/metasploit/framework/login_scanner/http.rb @@ -10,6 +10,7 @@ module LoginScanner class HTTP include Metasploit::Framework::LoginScanner::Base include Metasploit::Framework::LoginScanner::RexSocket + include Msf::Auxiliary::Report AUTHORIZATION_HEADER = 'WWW-Authenticate'.freeze DEFAULT_REALM = nil @@ -218,6 +219,8 @@ def check_setup end if authentication_required?(response) + # TODO: we might be able to do this, but look into potential false positives first. + # report_service(service) return false end @@ -274,18 +277,9 @@ def attempt_login(credential) result_opts = { credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, - proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(build_http_service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end - request_opts = {'credential'=>credential, 'uri'=>uri, 'method'=>method} if keep_connection_alive request_opts[:http_client] = create_client(request_opts) @@ -327,6 +321,75 @@ def authentication_required?(response) response.headers[self.class::AUTHORIZATION_HEADER] end + def build_http_service_opts + if ssl + { + name: 'https', + host: host, + port: port, + proto: 'tcp', + parents: [ + { + name: 'ssl', + host: host, + port: port, + proto: 'tcp', + parents: [ + { + name: 'tcp', + host: host, + port: port, + proto: 'tcp' + } + ] + } + ] + } + else + { + name: 'http', + host: host, + port: port, + proto: 'tcp', + parents: [ + { + name: 'tcp', + host: host, + port: port, + proto: 'tcp' + } + ] + } + end + end + + def service_as_result(service) + transform_map = { name: :service_name, proto: :protocol } + service.transform_keys { |key| transform_map[key] || key } + end + + def service_opts + raise NotImplementedError + end + + # @see Msf::Auxiliary::Report#db + def db + framework&.db&.active + end + + def build_service_opts(software_name) + parents = build_http_service_opts + + { + name: software_name.downcase, + host: host, + port: port, + proto: 'tcp', + resource: uri, + parents: [ parents ] + } + end + private def create_client(opts) diff --git a/lib/metasploit/framework/login_scanner/ipboard.rb b/lib/metasploit/framework/login_scanner/ipboard.rb index 0696e23f0e018..c7b4423593a4d 100644 --- a/lib/metasploit/framework/login_scanner/ipboard.rb +++ b/lib/metasploit/framework/login_scanner/ipboard.rb @@ -19,15 +19,8 @@ class IPBoard < HTTP def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end begin @@ -95,6 +88,10 @@ def method=(_) raise RuntimeError, "Method must be POST for IPBoard" end + def service_opts + build_service_opts('ipboard') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/ivanti_login.rb b/lib/metasploit/framework/login_scanner/ivanti_login.rb index cec57aff33318..2afc49dbc532e 100644 --- a/lib/metasploit/framework/login_scanner/ivanti_login.rb +++ b/lib/metasploit/framework/login_scanner/ivanti_login.rb @@ -27,6 +27,7 @@ def check_setup res = send_request(request_params) if res && res.code == 200 && res.body&.include?('Ivanti Connect Secure') + report_service(service_opts) return false end @@ -169,10 +170,7 @@ def attempt_login(credential) # focus on creating Result object, pass it to #login routine and return Result object result_options = { credential: credential, - host: @host, - port: @port, - protocol: 'tcp', - service_name: 'ivanti' + **service_as_result(service_opts) } if @use_admin_endpoint @@ -185,6 +183,10 @@ def attempt_login(credential) Result.new(result_options) end + def service_opts + build_service_opts('ivanti') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/jenkins.rb b/lib/metasploit/framework/login_scanner/jenkins.rb index ff4cc8096e71c..b5eee620ed2dc 100644 --- a/lib/metasploit/framework/login_scanner/jenkins.rb +++ b/lib/metasploit/framework/login_scanner/jenkins.rb @@ -5,12 +5,14 @@ module Framework module LoginScanner # Jenkins login scanner class Jenkins < HTTP + # Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP CAN_GET_SESSION = true DEFAULT_HTTP_NOT_AUTHED_CODES = [403] DEFAULT_PORT = 8080 PRIVATE_TYPES = [:password].freeze LOGIN_PATH_REGEX = /action="(j_([a-z0-9_]+))"/ + # TODO: We can potentially append 'Jenkins'/'jenkins' to the LIKELY_SERVICE_NAME as now our service fingerprinting is more granular. # Checks the setup for the Jenkins Login scanner. # @@ -22,6 +24,8 @@ def check_setup self.uri = normalize_uri(login_uri) + report_service(service_opts) + false end @@ -39,17 +43,9 @@ def set_sane_defaults def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end - status, proof = jenkins_login(credential.public, credential.private) result_opts.merge!(status: status, proof: proof) @@ -69,6 +65,11 @@ def authentication_required?(response) self.class::DEFAULT_HTTP_NOT_AUTHED_CODES.include?(response.code) end + # This needs some tweaking in order to work with credentials + def service_opts + build_service_opts('jenkins') + end + private # This method takes a username and password and a target URI diff --git a/lib/metasploit/framework/login_scanner/jupyter.rb b/lib/metasploit/framework/login_scanner/jupyter.rb index 163bf4c2a927a..ad2f47cec4309 100644 --- a/lib/metasploit/framework/login_scanner/jupyter.rb +++ b/lib/metasploit/framework/login_scanner/jupyter.rb @@ -23,10 +23,7 @@ def set_sane_defaults def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp', - service_name: ssl ? 'https' : 'http' + **service_as_result(service_opts) } begin @@ -55,6 +52,10 @@ def attempt_login(credential) end Result.new(result_opts) end + + def service_opts + build_service_opts('jupyter') + end end end end diff --git a/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb b/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb index c5f4882d2888c..4a8cd26ea9392 100644 --- a/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb +++ b/lib/metasploit/framework/login_scanner/manageengine_desktop_central.rb @@ -23,6 +23,7 @@ def check_setup fingerprint = 'ManageEngine Desktop Central' if res && res.body.include?(fingerprint) + report_service(service_opts) return false end @@ -115,10 +116,7 @@ def attempt_login(credential) credential: credential, status: LOGIN_STATUS::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp', - service_name: ssl ? 'https' : 'http', + **service_as_result(service_opts), } begin @@ -131,6 +129,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('manageengine_desktop_central') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/mybook_live.rb b/lib/metasploit/framework/login_scanner/mybook_live.rb index ba302104f52e8..ce508019062a3 100644 --- a/lib/metasploit/framework/login_scanner/mybook_live.rb +++ b/lib/metasploit/framework/login_scanner/mybook_live.rb @@ -23,15 +23,8 @@ def set_sane_defaults def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end begin res = send_request({ 'method' => method, @@ -54,6 +47,10 @@ def attempt_login(credential) end Result.new(result_opts) end + + def service_opts + build_service_opts('mybook_live') + end end end end diff --git a/lib/metasploit/framework/login_scanner/nessus.rb b/lib/metasploit/framework/login_scanner/nessus.rb index 04550ee5117ba..c666b97952cf3 100644 --- a/lib/metasploit/framework/login_scanner/nessus.rb +++ b/lib/metasploit/framework/login_scanner/nessus.rb @@ -22,6 +22,7 @@ def check_setup login_uri = "/server/properties" res = send_request({'uri'=> login_uri}) if res && res.body.include?('Nessus') + report_service(service_opts) return false end @@ -67,9 +68,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -89,6 +88,10 @@ def set_sane_defaults self.uri = '/session' end + def service_opts + build_service_opts('nessus') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/octopusdeploy.rb b/lib/metasploit/framework/login_scanner/octopusdeploy.rb index 298b30510fd7a..73bf7424b4d33 100644 --- a/lib/metasploit/framework/login_scanner/octopusdeploy.rb +++ b/lib/metasploit/framework/login_scanner/octopusdeploy.rb @@ -24,15 +24,8 @@ def set_sane_defaults def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end begin json_post_data = JSON.pretty_generate({ Username: credential.public, Password: credential.private }) res = send_request({ @@ -55,6 +48,10 @@ def attempt_login(credential) end Result.new(result_opts) end + + def service_opts + build_service_opts('octopusdeploy') + end end end end diff --git a/lib/metasploit/framework/login_scanner/opnsense.rb b/lib/metasploit/framework/login_scanner/opnsense.rb index 9ce58a86c79e5..8ca7b3b6605ec 100644 --- a/lib/metasploit/framework/login_scanner/opnsense.rb +++ b/lib/metasploit/framework/login_scanner/opnsense.rb @@ -28,6 +28,7 @@ def check_setup res = send_request(request_params) if res && res.code == 200 && res.body&.include?('Login | OPNsense') + report_service(service_opts) return false end @@ -97,10 +98,7 @@ def try_login(username, password, magic_value, cookies) def attempt_login(credential) result_options = { credential: credential, - host: @host, - port: @port, - protocol: 'tcp', - service_name: 'opnsense' + **service_as_result(service_opts) } # Each login needs its own magic name and value @@ -132,6 +130,10 @@ def attempt_login(credential) result_options.merge!(status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to OPNSense') return Result.new(result_options) end + + def service_opts + build_service_opts('opnsense') + end end end end diff --git a/lib/metasploit/framework/login_scanner/pfsense.rb b/lib/metasploit/framework/login_scanner/pfsense.rb index bc563bae04150..69fa558ec3186 100644 --- a/lib/metasploit/framework/login_scanner/pfsense.rb +++ b/lib/metasploit/framework/login_scanner/pfsense.rb @@ -21,6 +21,7 @@ def check_setup res = send_request(request_params) if res&.code == 200 && res.body&.include?('Login to pfSense') + report_service(service_opts) return false end @@ -75,10 +76,7 @@ def try_login(username, password, csrf_magic) def attempt_login(credential) result_options = { credential: credential, - host: @host, - port: @port, - protocol: 'tcp', - service_name: 'pfsense' + **service_as_result(service_opts) } # Each login needs its own csrf magic tokens @@ -110,6 +108,10 @@ def attempt_login(credential) result_options.merge!(status: ::Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: 'Unable to connect to pfSense') return Result.new(result_options) end + + def service_opts + build_service_opts('pfsense') + end end end end diff --git a/lib/metasploit/framework/login_scanner/phpmyadmin.rb b/lib/metasploit/framework/login_scanner/phpmyadmin.rb index a0f0a810990f3..a26ba74c4ec27 100644 --- a/lib/metasploit/framework/login_scanner/phpmyadmin.rb +++ b/lib/metasploit/framework/login_scanner/phpmyadmin.rb @@ -15,6 +15,7 @@ def check_setup version = Rex::Version.new($1).to_s if version.present? framework_module.print_status("PhpMyAdmin Version: #{version}") if framework_module + report_service(service_opts) return false end end @@ -72,15 +73,17 @@ def attempt_login(credential) credential: credential, status: LOGIN_STATUS::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } result_opts.merge!(do_login(credential.public, credential.private)) Result.new(result_opts) end + + def service_opts + build_service_opts('phpmyadmin') + end end end end diff --git a/lib/metasploit/framework/login_scanner/result.rb b/lib/metasploit/framework/login_scanner/result.rb index db1c373ccacd9..023e5caad7455 100644 --- a/lib/metasploit/framework/login_scanner/result.rb +++ b/lib/metasploit/framework/login_scanner/result.rb @@ -20,6 +20,9 @@ class Result # @!attribute port # @return [Integer] the port number of the service for this result attr_accessor :port + # @!attribute parents + # @return [Object] the service parents of this result's service. These get reported when creating credentials. + attr_accessor :parents # @!attribute proof # @return [#to_s] the proof of the login's success or failure attr_accessor :proof @@ -35,6 +38,9 @@ class Result # @!attribute connection # @return [Object] the post-authenticated connection object (if the scanner chooses to leave it open) attr_accessor :connection + # @!attribute resource + # @return [Object] the service's resource, if any, e.g. website URI + attr_accessor :resource validates :status, inclusion: { @@ -72,7 +78,9 @@ def to_h proof: proof, protocol: protocol, service_name: service_name, - status: status + status: status, + parents: parents, + resource: resource ) result_hash.delete_if { |k,v| v.nil? } end diff --git a/lib/metasploit/framework/login_scanner/smh.rb b/lib/metasploit/framework/login_scanner/smh.rb index c6cf2357fe561..65eb71a274c5a 100644 --- a/lib/metasploit/framework/login_scanner/smh.rb +++ b/lib/metasploit/framework/login_scanner/smh.rb @@ -16,7 +16,8 @@ class Smh < HTTP # (see Base#attempt_login) def attempt_login(credential) result_opts = { - credential: credential + credential: credential, + **service_as_result(service_opts) } req_opts = { @@ -49,6 +50,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('smh') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/softing_sis.rb b/lib/metasploit/framework/login_scanner/softing_sis.rb index 59e2e4741e5c6..0434c8344665d 100644 --- a/lib/metasploit/framework/login_scanner/softing_sis.rb +++ b/lib/metasploit/framework/login_scanner/softing_sis.rb @@ -26,6 +26,7 @@ def check_setup if res_json['version'] # report the version framework_module.print_brute(level: :good, ip: ip, msg: "Softing Secure Integration Server #{res_json['version']}") if framework_module + report_service(service_opts) return false end end @@ -149,9 +150,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -164,6 +163,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('softing_sis') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/sonicwall.rb b/lib/metasploit/framework/login_scanner/sonicwall.rb index 687863f2b9729..1ab90b8eab6ea 100644 --- a/lib/metasploit/framework/login_scanner/sonicwall.rb +++ b/lib/metasploit/framework/login_scanner/sonicwall.rb @@ -81,6 +81,7 @@ def check_setup } res = send_request(request_params) if res&.code == 200 && res.body&.include?('SonicWall') + report_service(service_opts) return false end @@ -139,14 +140,15 @@ def do_login(username, password, depth) def attempt_login(credential) result_options = { credential: credential, - host: @host, - port: @port, - protocol: 'tcp', - service_name: 'sonicwall' + **service_as_result(service_opts) } result_options.merge!(do_login(credential.public, credential.private, 1)) Result.new(result_options) end + + def service_opts + build_service_opts('sonicwall') + end end end end diff --git a/lib/metasploit/framework/login_scanner/symantec_web_gateway.rb b/lib/metasploit/framework/login_scanner/symantec_web_gateway.rb index 05926bfe5b04c..ac08911549022 100644 --- a/lib/metasploit/framework/login_scanner/symantec_web_gateway.rb +++ b/lib/metasploit/framework/login_scanner/symantec_web_gateway.rb @@ -22,6 +22,7 @@ def check_setup res = send_request({'uri'=> login_uri}) if res && res.body.include?('Symantec Web Gateway') + report_service(service_opts) return false end @@ -101,9 +102,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -116,6 +115,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('symantec_web_gateway') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/syncovery_file_sync_backup.rb b/lib/metasploit/framework/login_scanner/syncovery_file_sync_backup.rb index 94dd2c1f2a5fa..b792c4b4ab92c 100644 --- a/lib/metasploit/framework/login_scanner/syncovery_file_sync_backup.rb +++ b/lib/metasploit/framework/login_scanner/syncovery_file_sync_backup.rb @@ -20,6 +20,7 @@ def check_setup res = send_request({ 'uri' => login_uri }) if res && res.code == 200 && res.body.include?('Syncovery') + report_service(service_opts) return false end @@ -106,9 +107,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } begin @@ -121,6 +120,10 @@ def attempt_login(credential) Result.new(result_opts) end + def service_opts + build_service_opts('syncovery') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/teamcity.rb b/lib/metasploit/framework/login_scanner/teamcity.rb index 47bc29741e417..f62186f332d9a 100644 --- a/lib/metasploit/framework/login_scanner/teamcity.rb +++ b/lib/metasploit/framework/login_scanner/teamcity.rb @@ -152,6 +152,7 @@ def check_setup res = send_request(request_params) if res && res.code == 200 && res.body&.include?('Log in to TeamCity') + report_service(service_opts) return false end @@ -265,10 +266,7 @@ def logout_with_headers(headers) def attempt_login(credential) result_options = { credential: credential, - host: @host, - port: @port, - protocol: 'tcp', - service_name: 'teamcity' + **service_as_result(service_opts) } if @public_key.nil? @@ -288,6 +286,10 @@ def attempt_login(credential) Result.new(result_options) end + def service_opts + build_service_opts('teamcity') + end + private attr_accessor :public_key diff --git a/lib/metasploit/framework/login_scanner/wordpress_multicall.rb b/lib/metasploit/framework/login_scanner/wordpress_multicall.rb index 38e3fc8c34196..46fe3c4b3d85c 100644 --- a/lib/metasploit/framework/login_scanner/wordpress_multicall.rb +++ b/lib/metasploit/framework/login_scanner/wordpress_multicall.rb @@ -120,9 +120,7 @@ def attempt_login(credential) credential.private = pass result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL) return Result.new(result_opts) @@ -132,15 +130,17 @@ def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT) return Result.new(result_opts) end + def service_opts + build_service_opts('wordpress') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/wordpress_rpc.rb b/lib/metasploit/framework/login_scanner/wordpress_rpc.rb index cb770db1698f3..b48cdb3e119f9 100644 --- a/lib/metasploit/framework/login_scanner/wordpress_rpc.rb +++ b/lib/metasploit/framework/login_scanner/wordpress_rpc.rb @@ -11,15 +11,8 @@ class WordpressRPC < HTTP def attempt_login(credential) result_opts = { credential: credential, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } - if ssl - result_opts[:service_name] = 'https' - else - result_opts[:service_name] = 'http' - end begin @@ -68,6 +61,10 @@ def set_sane_defaults super end + def service_opts + build_service_opts('wordpress') + end + end end end diff --git a/lib/metasploit/framework/login_scanner/wowza_streaming_engine_manager.rb b/lib/metasploit/framework/login_scanner/wowza_streaming_engine_manager.rb index 35447de037ef8..334882dd1cff9 100644 --- a/lib/metasploit/framework/login_scanner/wowza_streaming_engine_manager.rb +++ b/lib/metasploit/framework/login_scanner/wowza_streaming_engine_manager.rb @@ -16,6 +16,7 @@ def check_setup res = send_request({ 'uri' => normalize_uri('/enginemanager/login.htm') }) if res && res.code == 200 && res.body.include?('Wowza Streaming Engine Manager') + report_service(service_opts) return false end @@ -33,9 +34,7 @@ def attempt_login(credential) credential: credential, status: Metasploit::Model::Login::Status::INCORRECT, proof: nil, - host: host, - port: port, - protocol: 'tcp' + **service_as_result(service_opts) } res = send_request({ @@ -60,6 +59,10 @@ def attempt_login(credential) Result.new(result_opts) end + + def service_opts + build_service_opts('wowza') + end end end end diff --git a/lib/metasploit/framework/login_scanner/zabbix.rb b/lib/metasploit/framework/login_scanner/zabbix.rb index ccff1076a83ed..10f95109972af 100644 --- a/lib/metasploit/framework/login_scanner/zabbix.rb +++ b/lib/metasploit/framework/login_scanner/zabbix.rb @@ -25,7 +25,10 @@ class Zabbix < HTTP # @param credential [Metasploit::Framework::Credential] The credential object # @return [Result] def attempt_login(credential) - result_opts = { credential: credential } + result_opts = { + credential: credential, + **service_as_result(service_opts) + } begin status = try_login(credential) @@ -63,6 +66,8 @@ def check_setup return "Unable to connect to target" end + report_service(service_opts) + false end @@ -146,6 +151,10 @@ def try_login(credential) end end + def service_opts + build_service_opts('zabbix') + end + end end end diff --git a/spec/lib/metasploit/framework/login_scanner/manageengine_desktop_central_spec.rb b/spec/lib/metasploit/framework/login_scanner/manageengine_desktop_central_spec.rb index bd665110ae2c3..82b3de51b4f5a 100644 --- a/spec/lib/metasploit/framework/login_scanner/manageengine_desktop_central_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/manageengine_desktop_central_spec.rb @@ -54,7 +54,9 @@ res end it 'returns false' do + allow(subject).to receive(:report_service) expect(subject.check_setup).to be(false) + expect(subject).to have_received(:report_service).with(hash_including(name: 'manageengine_desktop_central', proto: 'tcp')) end end diff --git a/spec/lib/metasploit/framework/login_scanner/nessus_spec.rb b/spec/lib/metasploit/framework/login_scanner/nessus_spec.rb index 58fdfe4f6faaf..d7d3fdcaec3c2 100644 --- a/spec/lib/metasploit/framework/login_scanner/nessus_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/nessus_spec.rb @@ -52,7 +52,9 @@ context 'when target is Nessus' do let(:response) { msp_html_response } it 'returns false' do + allow(http_scanner).to receive(:report_service) expect(http_scanner.check_setup).to be(false) + expect(http_scanner).to have_received(:report_service).with(hash_including(name: 'nessus', proto: 'tcp')) end end diff --git a/spec/lib/metasploit/framework/login_scanner/phpmyadmin_spec.rb b/spec/lib/metasploit/framework/login_scanner/phpmyadmin_spec.rb index 8980315c3162b..95458fba999b1 100644 --- a/spec/lib/metasploit/framework/login_scanner/phpmyadmin_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/phpmyadmin_spec.rb @@ -70,7 +70,9 @@ context 'when the version of PhpMyAdmin is detected' do let(:response) { phpMyAdmin_res } it 'should return false' do + allow(subject).to receive(:report_service) expect(subject.check_setup).to eql(false) + expect(subject).to have_received(:report_service).with(hash_including(name: 'phpmyadmin', proto: 'tcp')) end end diff --git a/spec/lib/metasploit/framework/login_scanner/symantec_web_gateway_spec.rb b/spec/lib/metasploit/framework/login_scanner/symantec_web_gateway_spec.rb index e6469417d8b71..51a30790d02bb 100644 --- a/spec/lib/metasploit/framework/login_scanner/symantec_web_gateway_spec.rb +++ b/spec/lib/metasploit/framework/login_scanner/symantec_web_gateway_spec.rb @@ -61,7 +61,9 @@ context 'when target is Symantec Web Gateway' do let(:response) { swg_html_response } it 'returns false' do + allow(subject).to receive(:report_service) expect(subject.check_setup).to be(false) + expect(subject).to have_received(:report_service).with(hash_including(name: 'symantec_web_gateway', proto: 'tcp')) end end