lib/msf/core/auxiliary/prometheus.rb
# -*- coding: binary -*-
module Msf
###
#
# This module provides methods for working with Prometheus node exporter
#
###
module Auxiliary::Prometheus
include Msf::Auxiliary::Report
# returns username, password
def process_authorization(auth)
if auth['credentials']
# credential foobar
return '', auth['credentials']
elsif auth['credentials_file']
# type: Bearer
# credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
return auth['type'], auth['credentials_file']
end
end
# processes a generic URI for creds
def process_embedded_uri(uri, job_name, config_name)
uri = URI(uri)
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = uri.user
cred[:private_data] = uri.password
cred[:service_name] = uri.scheme
create_credential_and_login(cred)
@table_creds << [
job_name,
config_name,
uri.host,
uri.port,
uri.user,
uri.password,
''
]
end
def credential_data
{
# these 4 need to be changed every time
# address: thost,
# port: tport,
# username: username
# private_data: hash
protocol: 'tcp',
workspace_id: myworkspace_id,
origin_type: :service,
private_type: :password,
service_name: '',
module_fullname: fullname,
status: Metasploit::Model::Login::Status::UNTRIED
}
end
def process_dns_sd_configs(job_name, dns_sd_configs)
dns_sd_configs['names']&.each do |name|
username = dns_sd_configs.dig('basic_auth', 'username')
password = dns_sd_configs.dig('basic_auth', 'password')
password = dns_sd_configs.dig('basic_auth', 'password_file') if dns_sd_configs.dig('basic_auth', 'password_file')
uri = URI("#{dns_sd_configs['scheme']}://#{name}")
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = dns_sd_configs.dig('basic_auth', 'username')
cred[:private_data] = password
cred[:service_name] = dns_sd_configs['scheme']
create_credential_and_login(cred)
@table_creds << [
job_name,
'dns_sd_configs',
uri.host,
uri.port,
username,
password,
''
]
end
end
def process_consul_sd_configs(job_name, consul_sd_configs)
uri = URI("#{consul_sd_configs['scheme']}://#{consul_sd_configs['server']}")
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = ''
cred[:private_data] = consul_sd_configs['token']
cred[:service_name] = consul_sd_configs['scheme']
create_credential_and_login(cred)
@table_creds << [
job_name,
'consul_sd_configs',
uri.host,
uri.port,
'',
consul_sd_configs['token'],
"Path Prefix: #{consul_sd_configs['path_prefix']}"
]
end
def process_kubernetes_sd_configs(job_name, kubernetes_sd_configs)
username = kubernetes_sd_configs.dig('basic_auth', 'username')
password = kubernetes_sd_configs.dig('basic_auth', 'password')
password = kubernetes_sd_configs.dig('basic_auth', 'password_file') if kubernetes_sd_configs.dig('basic_auth', 'password_file')
uri = URI(kubernetes_sd_configs['api_server'])
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = username
cred[:private_data] = password
cred[:service_name] = uri.scheme
create_credential_and_login(cred)
@table_creds << [
job_name,
'kubernetes_sd_configs',
uri.host,
uri.port,
username,
password,
"Role: #{kubernetes_sd_configs['role']}"
]
end
def process_kuma_sd_configs(job_name, targets)
return if targets['server'].nil?
return unless targets['server'].include? '@'
process_embedded_uri(targets['server'], job_name, 'kuma_sd_configs')
end
def process_marathon_sd_configs(job_name, marathon_sd_configs)
marathon_sd_configs['servers']&.each do |servers|
uri = URI(servers)
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = ''
cred[:private_data] = marathon_sd_configs['auth_token']
cred[:service_name] = uri.scheme
create_credential_and_login(cred)
@table_creds << [
job_name,
'marathon_sd_configs',
uri.host,
uri.port,
'',
marathon_sd_configs['auth_token'],
''
]
end
end
def process_nomad_sd_configs(job_name, targets)
return if targets['server'].nil?
return unless targets['server'].include? '@'
process_embedded_uri(targets['server'], job_name, 'nomad_sd_configs')
end
def process_ec2_sd_configs(job_name, ec2_sd_configs)
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = ec2_sd_configs['access_key']
cred[:private_data] = ec2_sd_configs['secret_key']
cred[:service_name] = ''
create_credential_and_login(cred)
@table_creds << [
job_name,
'ec2_sd_configs',
'',
'',
ec2_sd_configs['access_key'],
ec2_sd_configs['secret_key'],
"Region: #{ec2_sd_configs['region']}, Profile: #{ec2_sd_configs['profile']}"
]
end
def process_lightsail_sd_configs(job_name, lightsail_sd_configs)
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = lightsail_sd_configs['access_key']
cred[:private_data] = lightsail_sd_configs['secret_key']
cred[:service_name] = ''
create_credential_and_login(cred)
@table_creds << [
job_name,
'lightsail_sd_configs',
'',
'',
lightsail_sd_configs['access_key'],
lightsail_sd_configs['secret_key'],
"Region: #{lightsail_sd_configs['region']}, Profile: #{lightsail_sd_configs['profile']}"
]
end
def process_azure_sd_configs(job_name, azure_sd_configs)
cred = credential_data
cred[:port] = azure_sd_configs['port']
cred[:address] = ''
cred[:username] = azure_sd_configs['client_id']
cred[:private_data] = azure_sd_configs['client_secret']
cred[:service_name] = azure_sd_configs['authentication_method']
create_credential_and_login(cred)
@table_creds << [
job_name,
'azure_sd_configs',
'',
azure_sd_configs['port'],
azure_sd_configs['client_id'],
azure_sd_configs['client_secret'],
"Environment: #{azure_sd_configs['environment']}, Subscription ID: #{azure_sd_configs['subscription_id']}, Resource Group: #{azure_sd_configs['resource_group']}, Tenant ID: #{azure_sd_configs['tenant_id']}"
]
end
def process_http_sd_configs(job_name, http_sd_configs)
return if http_sd_configs['url'].nil?
return unless http_sd_configs['url'].include? '@'
process_embedded_uri(http_sd_configs['url'], job_name, 'http_sd_configs')
end
def process_digitalocean_sd_configs(job_name, digitalocean_sd_configs)
username, password = process_authorization(digitalocean_sd_configs['authorization'])
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = username
cred[:private_data] = password
create_credential_and_login(cred)
@table_creds << [
job_name,
'digitalocean_sd_configs',
'',
'',
username,
password,
''
]
end
def process_hetzner_sd_configs(job_name, hetzner_sd_configs)
username = hetzner_sd_configs.dig('basic_auth', 'username')
password = hetzner_sd_configs.dig('basic_auth', 'password')
username, password = process_authorization(hetzner_sd_configs['authorization']) if hetzner_sd_configs.dig('authorization', 'credentials')
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = username
cred[:private_data] = password
create_credential_and_login(cred)
@table_creds << [
job_name,
'hetzner_sd_configs',
'',
'',
username,
password,
hetzner_sd_configs['role']
]
end
def process_eureka_sd_configs(job_name, eureka_sd_configs)
return if eureka_sd_configs['server'].nil?
return unless eureka_sd_configs['server'].include? '@'
process_embedded_uri(eureka_sd_configs['server'], job_name, 'eureka_sd_configs')
end
def process_ovhcloud_sd_configs(job_name, ovhcloud_sd_configs)
cred = credential_data
cred[:port] = ''
cred[:address] = ovhcloud_sd_configs['endpoint']
cred[:username] = ovhcloud_sd_configs['application_key']
cred[:private_data] = ovhcloud_sd_configs['application_secret']
cred[:service_name] = ovhcloud_sd_configs['service']
create_credential_and_login(cred)
@table_creds << [
job_name,
'ovhcloud_sd_configs',
ovhcloud_sd_configs['endpoint'],
'',
ovhcloud_sd_configs['application_key'],
ovhcloud_sd_configs['application_secret'],
"Consumer Key: #{ovhcloud_sd_configs['consumer_key']}, Service: #{ovhcloud_sd_configs['service']}"
]
end
def process_scaleway_sd_configs(job_name, scaleway_sd_configs)
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = scaleway_sd_configs['access_key']
cred[:private_data] = scaleway_sd_configs['secret_key']
cred[:service_name] = scaleway_sd_configs['role']
create_credential_and_login(cred)
@table_creds << [
job_name,
'scaleway_sd_configs',
'',
'',
scaleway_sd_configs['access_key'],
scaleway_sd_configs['secret_key'],
"Project ID: #{scaleway_sd_configs['project_id']}, Role: #{scaleway_sd_configs['role']}"
]
end
def process_linode_sd_configs(job_name, linode_sd_configs)
username, password = process_authorization(linode_sd_configs['authorization'])
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = username
cred[:private_data] = password
create_credential_and_login(cred)
@table_creds << [
job_name,
'linode_sd_configs',
'',
'',
username,
password,
''
]
end
def process_uyuni_sd_configs(job_name, uyuni_sd_configs)
uri = URI(uyuni_sd_configs['server'])
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = uyuni_sd_configs['username']
cred[:private_data] = uyuni_sd_configs['password']
cred[:service_name] = uri.scheme
create_credential_and_login(cred)
@table_creds << [
job_name,
'uyuni_sd_configs',
uri.host,
uri.port,
uyuni_sd_configs['username'],
uyuni_sd_configs['password'],
''
]
end
def process_ionos_sd_configs(job_name, ionos_sd_configs)
_username, password = process_authorization(ionos_sd_configs['authorization'])
# we may hit an issue here where we have a type stored in username, but use datacenter_id
# as the username
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = ionos_sd_configs['datacenter_id']
cred[:private_data] = password
create_credential_and_login(cred)
@table_creds << [
job_name,
'ionos_sd_configs',
'',
'',
ionos_sd_configs['datacenter_id'],
password,
''
]
end
def process_vultr_sd_configs(job_name, vultr_sd_configs)
username, password = process_authorization(vultr_sd_configs['authorization'])
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = username
cred[:private_data] = password
create_credential_and_login(cred)
@table_creds << [
job_name,
'vultr_sd_configs',
'',
'',
username,
password,
''
]
end
def prometheus_config_eater(yamlconf)
@table_creds = Rex::Text::Table.new(
'Header' => 'Credentials',
'Indent' => 2,
'Columns' =>
[
'Name',
'Config',
'Host',
'Port',
'Public/Username',
'Private/Password/Token',
'Notes'
]
)
yamlconf['scrape_configs']&.each do |scrape|
# check for targets which have creds built in to the URL
if scrape['static_configs']
scrape['static_configs']&.each do |static|
static['targets']&.each do |target|
if target.include? '@'
uri = URI(target)
cred = credential_data
cred[:port] = uri.port
cred[:address] = uri.host
cred[:username] = uri.user
cred[:private_data] = uri.password
cred[:service_name] = uri.scheme
create_credential_and_login(cred)
@table_creds << [
scrape['job_name'],
'static_configs Target',
uri.host,
uri.port,
uri.user,
uri.password,
''
]
end
end
end
elsif scrape['dns_sd_configs']
scrape['dns_sd_configs']&.each do |dns_sd_configs|
# pass in basic_auth from the level above
if dns_sd_configs['basic_auth'].nil? && scrape['basic_auth']
dns_sd_configs['basic_auth'] = {}
dns_sd_configs['basic_auth']['username'] = scrape.dig('basic_auth', 'username') if scrape.dig('basic_auth', 'username')
dns_sd_configs['basic_auth']['password'] = scrape.dig('basic_auth', 'password') if scrape.dig('basic_auth', 'password')
dns_sd_configs['basic_auth']['password_file'] = scrape.dig('basic_auth', 'password_file') if scrape.dig('basic_auth', 'password_file')
end
# pass in the 'scheme' from a level above to properly build the URI
if dns_sd_configs['scheme'].nil? && scrape['scheme']
dns_sd_configs['scheme'] = scrape['scheme']
end
process_dns_sd_configs(scrape['job_name'], dns_sd_configs)
end
elsif scrape['consul_sd_configs']
scrape['consul_sd_configs']&.each do |consul_sd_configs|
process_consul_sd_configs(scrape['job_name'], consul_sd_configs)
end
elsif scrape['authorization']
username, password = process_authorization(scrape['authorization'])
cred = credential_data
cred[:port] = ''
cred[:address] = ''
cred[:username] = username
cred[:private_data] = password
create_credential_and_login(cred)
@table_creds << [
scrape['job_name'],
'authorization',
'',
'',
username,
password,
''
]
elsif scrape['kubernetes_sd_configs']
scrape['kubernetes_sd_configs']&.each do |kubernetes_sd_configs|
next unless kubernetes_sd_configs['api_server']
# if scrape has basic auth, but the individual config doesn't
# add it to the individual config
if kubernetes_sd_configs['basic_auth'].nil? && scrape['basic_auth']
kubernetes_sd_configs['basic_auth'] = {}
kubernetes_sd_configs['basic_auth']['username'] = scrape.dig('basic_auth', 'username') if scrape.dig('basic_auth', 'username')
kubernetes_sd_configs['basic_auth']['password'] = scrape.dig('basic_auth', 'password') if scrape.dig('basic_auth', 'password')
kubernetes_sd_configs['basic_auth']['password'] = scrape.dig('basic_auth', 'password_file') if scrape.dig('basic_auth', 'password_file')
end
process_kubernetes_sd_configs(scrape['job_name'], kubernetes_sd_configs)
end
elsif scrape['kuma_sd_configs']
scrape['kuma_sd_configs']&.each do |targets|
process_kuma_sd_configs(scrape['job_name'], targets)
end
elsif scrape['marathon_sd_configs']
scrape['marathon_sd_configs']&.each do |marathon_sd_configs|
process_marathon_sd_configs(scrape['job_name'], marathon_sd_configs)
end
elsif scrape['nomad_sd_configs']
scrape['nomad_sd_configs']&.each do |targets|
process_nomad_sd_configs(scrape['job_name'], targets)
end
elsif scrape['ec2_sd_configs']
scrape['ec2_sd_configs']&.each do |ec2_sd_configs|
process_ec2_sd_configs(scrape['job_name'], ec2_sd_configs)
end
elsif scrape['lightsail_sd_configs']
scrape['lightsail_sd_configs']&.each do |lightsail_sd_configs|
process_lightsail_sd_configs(scrape['job_name'], lightsail_sd_configs)
end
elsif scrape['azure_sd_configs']
scrape['azure_sd_configs']&.each do |azure_sd_configs|
process_azure_sd_configs(scrape['job_name'], azure_sd_configs)
end
elsif scrape['http_sd_configs']
scrape['http_sd_configs']&.each do |http_sd_configs|
process_http_sd_configs(scrape['job_name'], http_sd_configs)
end
elsif scrape['digitalocean_sd_configs']
scrape['digitalocean_sd_configs']&.each do |digitalocean_sd_configs|
process_digitalocean_sd_configs(scrape['job_name'], digitalocean_sd_configs)
end
elsif scrape['hetzner_sd_configs']
scrape['hetzner_sd_configs']&.each do |hetzner_sd_configs|
process_hetzner_sd_configs(scrape['job_name'], hetzner_sd_configs)
end
elsif scrape['eureka_sd_configs']
scrape['eureka_sd_configs']&.each do |eureka_sd_configs|
process_eureka_sd_configs(scrape['job_name'], eureka_sd_configs)
end
elsif scrape['ovhcloud_sd_configs']
scrape['ovhcloud_sd_configs']&.each do |ovhcloud_sd_configs|
process_ovhcloud_sd_configs(scrape['job_name'], ovhcloud_sd_configs)
end
elsif scrape['scaleway_sd_configs']
scrape['scaleway_sd_configs']&.each do |scaleway_sd_configs|
process_scaleway_sd_configs(scrape['job_name'], scaleway_sd_configs)
end
elsif scrape['linode_sd_configs']
scrape['linode_sd_configs']&.each do |linode_sd_configs|
process_linode_sd_configs(scrape['job_name'], linode_sd_configs)
end
elsif scrape['uyuni_sd_configs']
scrape['uyuni_sd_configs']&.each do |uyuni_sd_configs|
process_uyuni_sd_configs(scrape['job_name'], uyuni_sd_configs)
end
elsif scrape['ionos_sd_configs']
scrape['ionos_sd_configs']&.each do |ionos_sd_configs|
process_ionos_sd_configs(scrape['job_name'], ionos_sd_configs)
end
elsif scrape['vultr_sd_configs']
scrape['vultr_sd_configs']&.each do |vultr_sd_configs|
process_vultr_sd_configs(scrape['job_name'], vultr_sd_configs)
end
end
end
print_good(@table_creds.to_s) if !@table_creds.rows.empty?
end
def process_results_page(page)
# data is in a strange 'label{optional_kv_hash-ish} value' format.
return nil if page.nil?
results = []
page.scan(/^(?<name>\w+)(?:{(?<labels>[^}]+)})? (?<value>[\w.+-]+)/).each do |hit|
result = {}
value = { 'value' => hit[2], 'labels' => {} }
if hit[1]
hit[1].scan(/(?<key>[^=]+?)="(?<value>[^"]*)",?/).each do |label|
value['labels'][label[0]] = label[1]
end
end
result[hit[0]] = value
results.append(result)
end
return results
end
end
end