124 lines
3.8 KiB
Ruby
124 lines
3.8 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'aws-sdk-iam'
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Amazon Web Services IAM credential enumeration',
|
|
'Description' => %q(
|
|
Provided AWS credentials, this module will call the authenticated
|
|
API of Amazon Web Services to list all IAM credentials associated
|
|
with the account
|
|
),
|
|
'Author' => ['Aaron Soto <aaron.soto@rapid7.com>'],
|
|
'License' => MSF_LICENSE
|
|
)
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
OptString.new('ACCESS_KEY_ID', [true, 'AWS Access Key ID (eg. "AKIAXXXXXXXXXXXXXXXX")', '']),
|
|
OptString.new('SECRET_ACCESS_KEY', [true, 'AWS Secret Access Key (eg. "CA1+XXXXXXXXXXXXXXXXXXXXXX6aYDHHCBuLuV79")', ''])
|
|
]
|
|
)
|
|
end
|
|
|
|
def handle_aws_errors(e)
|
|
if e.class.module_parents.include?(Aws)
|
|
fail_with(Failure::UnexpectedReply, e.message)
|
|
else
|
|
raise e
|
|
end
|
|
end
|
|
|
|
def describe_iam_users(i)
|
|
user = i.user_name
|
|
|
|
print_good " User Name: #{user}"
|
|
print_good " User ID: #{i.user_id}"
|
|
print_good " Creation Date: #{i.create_date}"
|
|
print_good " Tags: #{i.tags}"
|
|
print_good " Groups: #{i.group_list}"
|
|
print_good " SSH Pub Keys: #{@iam.list_ssh_public_keys(user_name: user).ssh_public_keys}"
|
|
|
|
policies = i.attached_managed_policies
|
|
if policies.empty?
|
|
print_good " Policies: []"
|
|
else
|
|
print_good " Policies: #{policies[0].policy_name}"
|
|
policies[1..policies.length].each do |p|
|
|
print_good " #{p.policy_name}"
|
|
end
|
|
end
|
|
|
|
certs = @iam.list_signing_certificates(user_name: user).certificates
|
|
if certs.empty?
|
|
print_good " Signing certs: []"
|
|
else
|
|
print_good " Signing certs: #{certs[0].certificate_id} (#{certs[0].status})"
|
|
certs[1..certs.length].each do |c|
|
|
print_good " #{c.certificate_id} (#{c.status})"
|
|
end
|
|
end
|
|
|
|
@users.each do |u|
|
|
if u.user_name == user
|
|
print_good " Password Used: #{u.password_last_used || '(Never)'}"
|
|
end
|
|
end
|
|
|
|
keys = @iam.list_access_keys(user_name: user).access_key_metadata
|
|
if keys.empty?
|
|
print_good " AWS Access Keys: []"
|
|
else
|
|
print_good " AWS Access Keys: #{keys[0].access_key_id} (#{keys[0].status})"
|
|
keys[1..keys.length].each do |k|
|
|
print_good " #{k.access_key_id} (#{k.status})"
|
|
end
|
|
end
|
|
|
|
begin
|
|
console_login = @iam.get_login_profile(user_name: user).empty? ? 'Disabled' : 'Enabled'
|
|
print_good " Console login: #{console_login}"
|
|
rescue Aws::IAM::Errors::NoSuchEntity
|
|
print_good " Console login: Disabled"
|
|
end
|
|
|
|
mfa = @iam.list_mfa_devices(user_name: i.user_name).mfa_devices
|
|
mfa_enabled = mfa.empty? ? 'Disabled' : "Enabled on #{mfa[0].enable_date}"
|
|
print_good " Two-factor auth: #{mfa_enabled}"
|
|
|
|
print_status ''
|
|
end
|
|
|
|
def run
|
|
@iam = Aws::IAM::Client.new(
|
|
region: 'us-west-1', # This is meaningless, but required. Thanks AWS.
|
|
access_key_id: datastore['ACCESS_KEY_ID'],
|
|
secret_access_key: datastore['SECRET_ACCESS_KEY']
|
|
)
|
|
|
|
@users = @iam.list_users.users
|
|
creds = @iam.get_account_authorization_details
|
|
|
|
users = creds.user_detail_list
|
|
if users.empty?
|
|
print_status 'No users found.'
|
|
return
|
|
end
|
|
|
|
print_good "Found #{users.count} users."
|
|
users.each do |i|
|
|
describe_iam_users(i)
|
|
end
|
|
rescue ::Exception => e
|
|
handle_aws_errors(e)
|
|
end
|
|
end
|