Module: Msf::Exploit::Cacti

Includes:
Remote::HttpClient
Defined in:
lib/msf/core/exploit/cacti.rb

Defined Under Namespace

Classes: CactiCsrfNotFoundError, CactiError, CactiLoginError, CactiNoAccessError, CactiNotFoundError, CactiVersionNotFoundError

Instance Attribute Summary

Attributes included from Remote::HttpClient

#client, #cookie_jar

Instance Method Summary collapse

Methods included from Remote::HttpClient

#basic_auth, #cleanup, #configure_http_login_scanner, #connect, #connect_ws, #deregister_http_client_options, #disconnect, #download, #full_uri, #handler, #http_fingerprint, #initialize, #lookup_http_fingerprints, #normalize_uri, #path_from_uri, #peer, #proxies, #reconfig_redirect_opts!, #request_opts_from_url, #request_url, #rhost, #rport, #send_request_cgi, #send_request_cgi!, #send_request_raw, #service_details, #setup, #ssl, #ssl_version, #strip_tags, #target_uri, #validate_fingerprint, #vhost

Methods included from Auxiliary::LoginScanner

#configure_login_scanner

Methods included from Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Metasploit::Framework::Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Instance Method Details

#do_login(username, password, csrf_token: nil) ⇒ Object

Log in to Cacti. It will take care of grabbing the CSRF token if not provided.

Parameters:

  • username (String)

    The username

  • password (String)

    The password

Raises:



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/msf/core/exploit/cacti.rb', line 75

def (username, password, csrf_token: nil)
  if csrf_token.blank?
    print_status('Getting the CSRF token to login')
    begin
      csrf_token = get_csrf_token
    rescue CactiError => e
      raise CactiLoginError, "Unable to login: #{e.class} - #{e}"
    end

    vprint_good("CSRF token: #{csrf_token}")
  end

  print_status("Attempting login with user `#{username}` and password `#{password}`")
  res = send_request_cgi(
    'uri' => normalize_uri(target_uri.path, 'index.php'),
    'method' => 'POST',
    'keep_cookies' => true,
    'vars_post' => {
      '__csrf_magic' => csrf_token,
      'action' => 'login',
      'login_username' => username,
      'login_password' => password
    }
  )
  raise CactiNoAccessError, 'Could not login - no response' if res.nil?
  raise CactiLoginError, "Login failure - unexpected HTTP response code: #{res.code}" unless res.code == 302

  print_good('Logged in')

  nil
end

#get_csrf_tokenString

Get the CSRF token by querying the ‘index.php` web page and extracting it from the response.

Returns:

  • (String)

    The CSRF token

Raises:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/msf/core/exploit/cacti.rb', line 53

def get_csrf_token
  res = send_request_cgi(
    'uri' => normalize_uri(target_uri.path, 'index.php'),
    'method' => 'GET',
    'keep_cookies' => true
  )
  raise CactiNoAccessError, 'Could not access `index.php` - no response' if res.nil?

  html = res.get_html_document
  csrf_token = parse_csrf_token(html)
  raise CactiCsrfNotFoundError, 'Unable to get the CSRF token' if csrf_token.empty?

  csrf_token
end

#parse_csrf_token(html) ⇒ String

Extract the CSRF token from an HTML response

Parameters:

  • html (Nokogiri::HTML::Document)

    The HTML response to parse

Returns:

  • (String)

    The CSRF token



43
44
45
# File 'lib/msf/core/exploit/cacti.rb', line 43

def parse_csrf_token(html)
  html.xpath('//form/input[@name="__csrf_magic"]/@value').text
end

#parse_version(html) ⇒ String

Extract the version number from an HTML response

Parameters:

  • html (Nokogiri::HTML::Document)

    The HTML response

Returns:

  • (String)

    The version number

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/msf/core/exploit/cacti.rb', line 26

def parse_version(html)
  # This will return an empty string if there is no match
  version_str = html.xpath('//div[@class="versionInfo"]').text
  unless version_str.include?('The Cacti Group')
    raise CactiNotFoundError, 'The web server is not running Cacti'
  end
  unless version_str.match(/Version (?<version>\d{1,2}[.]\d{1,2}[.]\d{1,2})/)
    raise CactiVersionNotFoundError, 'Could not detect the version'
  end

  Regexp.last_match[:version]
end