## # 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 '], 'License' => MSF_LICENSE, 'Notes' => { 'Stability' => [CRASH_SAFE], 'SideEffects' => [IOC_IN_LOGS], 'Reliability' => [] } ) ) 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(error) if error.class.module_parents.include?(Aws) fail_with(Failure::UnexpectedReply, error.message) else raise error end end def describe_iam_users(user) print_good " User Name: #{user.user_name}" print_good " User ID: #{user.user_id}" print_good " Creation Date: #{user.create_date}" print_good " Tags: #{user.tags}" print_good " Groups: #{user.group_list}" print_good " SSH Pub Keys: #{@iam.list_ssh_public_keys(user_name: user.user_name).ssh_public_keys}" policies = user.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.user_name).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.user_name print_good " Password Used: #{u.password_last_used || '(Never)'}" end end keys = @iam.list_access_keys(user_name: user.user_name).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.user_name).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: user.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 |user| describe_iam_users(user) end rescue StandardError => e handle_aws_errors(e) end end