Module: Msf::Exploit::Remote::HTTP::Jenkins

Included in:
Metasploit::Framework::LoginScanner::Jenkins
Defined in:
lib/msf/core/exploit/remote/http/jenkins.rb

Overview

This module provides a way of logging into Jenkins

Instance Method Summary collapse

Instance Method Details

#jenkins_login(username, password, target_uri = nil) ⇒ Array

This method takes a username and password and a target URI then attempts to login to Jenkins and will either fail with appropriate errors

Parameters:

  • username (String)

    The username for login credentials

  • password (String)

    The password for login credentials

Returns:

  • (Array)
    status, proof

    The result of the login attempt



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/msf/core/exploit/remote/http/jenkins.rb', line 54

def (username, password, target_uri = nil)
  begin
    request = {
      'vars_post' =>
        {
          'j_username' => username,
          'j_password' => password,
          'Submit' => 'log in'
        }
    }

    if block_given?
      res = yield request
    else
      res = send_request_cgi({
        'method' => 'POST',
        'uri' => normalize_uri(target_uri),
        'keep_cookies' => true,
        'vars_post' => request['vars_post']
      })
    end

    if res && res.headers['location'] && !res.headers['location'].include?('loginError')
      status = Metasploit::Model::Login::Status::SUCCESSFUL
      proof = res.headers
    else
      status = Metasploit::Model::Login::Status::INCORRECT
      proof = res
    end
  rescue ::EOFError, Errno::ETIMEDOUT, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
    status = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT
    proof = e
  end

  [status, proof]
end

#jenkins_uri_check(target_uri, keep_cookies: false) ⇒ String

This method takes a target URI and makes a request to verify if logging in is possible, otherwise it will fail gracefully

Parameters:

  • target_uri (URI, String)

    The targets URI

Returns:

  • (String)

    URI for successful login



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/msf/core/exploit/remote/http/jenkins.rb', line 35

def jenkins_uri_check(target_uri, keep_cookies: false)
  # if keep_cookies is true we get the first cookie that's needed by newer Jenkins versions
  res = send_request_cgi({ 'uri' => normalize_uri(target_uri, 'login'), 'keep_cookies' => keep_cookies })
  fail_with(Msf::Module::Failure::UnexpectedReply, 'Unexpected reply from server') unless res&.code == 200
  if res.body =~ /action="(j_([a-z0-9_]+))"/
    uri = Regexp.last_match(1)
  else
    fail_with(Msf::Module::Failure::UnexpectedReply, 'Failed to identify the login resource.')
  end

  normalize_uri(target_uri, uri)
end

#jenkins_versionString, NilClass

Returns the Jenkins version.

Returns:

  • (String)

    Jenkins version.

  • (NilClass)

    No Jenkins version found.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/msf/core/exploit/remote/http/jenkins.rb', line 13

def jenkins_version
  uri = normalize_uri(target_uri.path)
  res = send_request_cgi({ 'uri' => uri })

  unless res
    return nil 
  end

  # shortcut for new versions such as 2.426.2 and 2.440
  return res.headers['X-Jenkins'] if res.headers['X-Jenkins']

  html = res.get_html_document
  version_attribute = html.at('body').attributes['data-version']
  version = version_attribute ? version_attribute.value : ''
  version.scan(/jenkins-([\d.]+)/).flatten.first
end