## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'aws-sdk-ec2' class MetasploitModule < Msf::Auxiliary def initialize(info = {}) super( update_info( info, 'Name' => 'Amazon Web Services EC2 instance enumeration', 'Description' => %q( Provided AWS credentials, this module will call the authenticated API of Amazon Web Services to list all EC2 instances associated with the account ), 'Author' => ['Aaron Soto '], 'License' => MSF_LICENSE ) ) register_options( [ OptInt.new('LIMIT', [false, 'Only return the specified number of results from each region']), OptString.new('REGION', [false, 'AWS Region (eg. "us-west-2")']), 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.parents.include?(Aws) fail_with(Failure::UnexpectedReply, e.message) else raise e end end def enumerate_regions regions = [] ec2 = Aws::EC2::Resource.new( region: 'us-west-1', access_key_id: datastore['ACCESS_KEY_ID'], secret_access_key: datastore['SECRET_ACCESS_KEY'] ) ec2_regions = ec2.client.describe_regions.data.regions ec2_regions.each do |r| regions.append(r.region_name) end regions end def describe_ec2_instance(i) print_good " #{i.id} (#{i.state.name})" print_good " Creation Date: #{i.launch_time}" print_good " Public IP: #{i.public_ip_address} (#{i.public_dns_name})" print_good " Private IP: #{i.public_ip_address} (#{i.private_dns_name})" i.security_groups.each do |s| print_good " Security Group: #{s.group_id}" end end def run regions = datastore['REGION'] ? [datastore['REGION']] : regions = enumerate_regions() regions.each do |region| vprint_status "Checking #{region}..." ec2 = Aws::EC2::Resource.new( region: region, access_key_id: datastore['ACCESS_KEY_ID'], secret_access_key: datastore['SECRET_ACCESS_KEY'] ) instances = ec2.instances.limit(datastore['LIMIT']) print_status "Found #{ec2.instances.count} instances in #{region}" instances.each do |i| describe_ec2_instance(i) end end rescue Seahorse::Client::NetworkingError => e print_error e.message print_error 'Confirm region name (eg. us-west-2) is valid or blank before retrying' rescue ::Exception => e handle_aws_errors(e) end end