CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/lib/metasploit/framework/login_scanner/jenkins.rb
Views: 1904
require 'metasploit/framework/login_scanner/http'12module Metasploit3module Framework4module LoginScanner5# Jenkins login scanner6class Jenkins < HTTP7# Inherit LIKELY_PORTS,LIKELY_SERVICE_NAMES, and REALM_KEY from HTTP8CAN_GET_SESSION = true9DEFAULT_HTTP_NOT_AUTHED_CODES = [403]10DEFAULT_PORT = 808011PRIVATE_TYPES = [:password].freeze12LOGIN_PATH_REGEX = /action="(j_([a-z0-9_]+))"/1314# Checks the setup for the Jenkins Login scanner.15#16# @return [String, false] Always returns false.17def check_setup18login_uri = jenkins_login_url1920return 'Unable to locate the Jenkins login path' if login_uri.nil?2122self.uri = normalize_uri(login_uri)2324false25end2627# (see Base#set_sane_defaults)28def set_sane_defaults29self.uri ||= '/'3031unless uri.to_s.start_with?('/')32self.uri = "/#{uri}"33end3435super36end3738def attempt_login(credential)39result_opts = {40credential: credential,41host: host,42port: port,43protocol: 'tcp'44}4546if ssl47result_opts[:service_name] = 'https'48else49result_opts[:service_name] = 'http'50end5152status, proof = jenkins_login(credential.public, credential.private)5354result_opts.merge!(status: status, proof: proof)5556Result.new(result_opts)57end5859protected6061# Returns a boolean value indicating whether the request requires authentication or not.62#63# @param [Rex::Proto::Http::Response] response The response received from the HTTP endpoint64# @return [Boolean] True if the request required authentication; otherwise false.65def authentication_required?(response)66return false unless response6768self.class::DEFAULT_HTTP_NOT_AUTHED_CODES.include?(response.code)69end7071private7273# This method takes a username and password and a target URI74# then attempts to login to Jenkins and will either fail with appropriate errors75#76# @param [String] username The username for login credentials77# @param [String] password The password for login credentials78# @return [Array] [status, proof] The result of the login attempt79def jenkins_login(username, password)80begin81res = send_request(82'method' => 'POST',83'uri' => self.uri,84'vars_post' => {85'j_username' => username,86'j_password' => password,87'Submit' => 'log in'88}89)9091if res && res.headers['Location'] && !res.headers['Location'].include?('loginError')92status = Metasploit::Model::Login::Status::SUCCESSFUL93proof = res.headers94else95status = Metasploit::Model::Login::Status::INCORRECT96proof = res97end98rescue ::EOFError, Errno::ETIMEDOUT, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e99status = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT100proof = e101end102103[status, proof]104end105106# This method uses the provided URI to determine whether login is possible for Jenkins.107# Based on the contents of the provided URI, the method looks for the login form and108# extracts the endpoint used to authenticate against.109#110# @return [String, nil] URI for successful login111def jenkins_login_url112response = send_request({ 'uri' => normalize_uri('login') })113114if response&.code == 200 && response&.body =~ LOGIN_PATH_REGEX115return Regexp.last_match(1)116end117118nil119end120121# Determines whether the provided response is considered valid or not.122#123# @param [Rex::Proto::Http::Response, nil] response The response received from the HTTP request.124# @return [Boolean] True if the response if valid; otherwise false.125def valid_response?(response)126http_success_codes.include?(response&.code)127end128end129end130end131end132133134