Path: blob/master/modules/auxiliary/cloud/aws/enum_ec2.rb
19500 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'aws-sdk-ec2'67class MetasploitModule < Msf::Auxiliary8include Msf::Auxiliary::Report9def initialize(info = {})10super(11update_info(12info,13'Name' => 'Amazon Web Services EC2 instance enumeration',14'Description' => %q{15Provided AWS credentials, this module will call the authenticated16API of Amazon Web Services to list all EC2 instances associated17with the account18},19'Author' => [20'Aaron Soto <[email protected]>',21'RageLtMan <rageltman[at]sempervictus>'22],23'License' => MSF_LICENSE,24'Notes' => {25'SideEffects' => [IOC_IN_LOGS],26'Stability' => [CRASH_SAFE],27'Reliability' => []28}29)30)3132register_options(33[34OptInt.new('LIMIT', [false, 'Only return the specified number of results from each region']),35OptString.new('REGION', [false, 'AWS Region (eg. "us-west-2")']),36OptString.new('ACCESS_KEY_ID', [true, 'AWS Access Key ID (eg. "AKIAXXXXXXXXXXXXXXXX")', '']),37OptString.new('SECRET_ACCESS_KEY', [true, 'AWS Secret Access Key (eg. "CA1+XXXXXXXXXXXXXXXXXXXXXX6aYDHHCBuLuV79")', ''])38]39)40end4142def enumerate_regions43regions = []4445ec2 = Aws::EC2::Resource.new(46region: 'us-west-1',47access_key_id: datastore['ACCESS_KEY_ID'],48secret_access_key: datastore['SECRET_ACCESS_KEY']49)5051ec2_regions = ec2.client.describe_regions.data.regions52ec2_regions.each do |r|53regions.append(r.region_name)54end5556regions57end5859def describe_ec2_instance(inst)60print_good " #{inst.id} (#{inst.state.name})"61print_good " Creation Date: #{inst.launch_time}"62print_good " Public IP: #{inst.public_ip_address} (#{inst.public_dns_name})"63print_good " Private IP: #{inst.private_ip_address} (#{inst.private_dns_name})"64# Report hosts and info65mac_addr = inst.network_interfaces.select do |iface|66iface.private_ip_address == inst.private_ip_address67end.first.mac_address68iname = inst.tags.find { |t| t.key == 'Name' } ? inst.tags.find { |t| t.key == 'Name' }.value : inst.private_dns_name69iinfo = inst.tags.find { |t| t.key == 'Description' } ? inst.tags.find { |t| t.key == 'Description' }.value : nil70report_host(71host: inst.private_ip_address,72mac: mac_addr,73os_name: inst.platform_details,74os_flavor: inst.architecture,75name: iname,76info: iinfo,77comments: "ec2-id: #{inst.id} (#{inst.placement.availability_zone})"78)79if inst.public_ip_address80report_note(81host: inst.private_ip_address,82type: 'ec2.public_ip',83data: { :public_ip_address => inst.public_ip_address }84)85end86# eips = inst.network_interfaces.map {|i| i.association && i.association.public_ip}.compact # <-- works in pry, breaks at runtime in AWS SDK87# report_note(88# host: inst.private_ip_address,89# type: 'ec2.public_ips',90# data: { :eips => eips.join(' ') }91# ) unless eips.empty?92if inst.public_ip_address && !inst.public_dns_name.empty?93report_note(94host: inst.private_ip_address,95type: 'ec2.public_dns',96data: {97:public_dns_name => inst.public_dns_name,98:public_ip_address => inst.public_ip_address99}100)101end102if inst.hypervisor103report_note(104host: inst.private_ip_address,105type: 'ec2.hypervisor',106data: { :hypervisor => inst.hypervisor }107)108end109inst.security_groups.each do |s|110print_good " Security Group: #{s.group_id}"111report_note(112host: inst.private_ip_address,113type: "ec2.#{s.group_id}",114data: { :group_name => s.group_name }115)116end117inst.tags.each do |t|118print_good " Tag: #{t.key} = #{t.value}"119report_note(120host: inst.private_ip_address,121type: "ec2.tag #{t.key}",122data: { :tag => t.value }123)124end125end126127def run128all_regions = enumerate_regions129if datastore['REGION'].blank?130regions = all_regions131elsif !all_regions.include?(datastore['REGION'])132fail_with(Failure::BadConfig, "Invalid AWS region: #{datastore['REGION']}")133else134regions = [datastore['REGION']]135end136137regions.uniq.each do |region|138vprint_status "Checking #{region}..."139ec2 = Aws::EC2::Resource.new(140region: region,141access_key_id: datastore['ACCESS_KEY_ID'],142secret_access_key: datastore['SECRET_ACCESS_KEY']143)144145instances = datastore['LIMIT'] ? ec2.instances.limit(datastore['LIMIT']) : ec2.instances146print_status "Found #{ec2.instances.count} instances in #{region}"147148instances.each do |i|149describe_ec2_instance(i)150end151end152rescue Seahorse::Client::NetworkingError => e153print_error e.message154print_error 'Confirm region name (eg. us-west-2) is valid or blank before retrying'155rescue Aws::EC2::Errors::ServiceError => e156fail_with(Failure::UnexpectedReply, e.message)157end158end159160161