Path: blob/master/modules/auxiliary/cloud/aws/enum_s3.rb
19500 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'aws-sdk-s3'67class MetasploitModule < Msf::Auxiliary8def initialize(info = {})9super(10update_info(11info,12'Name' => 'Amazon Web Services S3 instance enumeration',13'Description' => %q{14Provided AWS credentials, this module will call the authenticated15API of Amazon Web Services to list all S3 buckets associated16with the account17},18'Author' => ['Aaron Soto <[email protected]>'],19'License' => MSF_LICENSE,20'Notes' => {21'Stability' => [CRASH_SAFE],22'SideEffects' => [IOC_IN_LOGS],23'Reliability' => []24}25)26)2728register_options(29[30OptString.new('REGION', [false, 'AWS Region (eg. "us-west-2")']),31OptString.new('ACCESS_KEY_ID', [true, 'AWS Access Key ID (eg. "AKIAXXXXXXXXXXXXXXXX")', '']),32OptString.new('SECRET_ACCESS_KEY', [true, 'AWS Secret Access Key (eg. "CA1+XXXXXXXXXXXXXXXXXXXXXX6aYDHHCBuLuV79")', ''])33]34)35end3637def handle_aws_errors(error)38if error.class.module_parents.include?(Aws)39fail_with(Failure::UnexpectedReply, error.message)40else41raise error42end43end4445def describe_s3_bucket(bucket)46print_good " Name: #{bucket.name}"47print_good " Creation Date: #{bucket.creation_date}"48print_good " # of Objects: #{@s3.list_objects_v2(bucket: bucket.name).contents.length}"49print_good " Region: #{@s3.get_bucket_location(bucket: bucket.name).location_constraint}"5051begin52print_good " Website: /#{@s3.get_bucket_website(bucket: bucket.name).index_document.suffix}"53rescue Aws::S3::Errors::NoSuchWebsiteConfiguration54print_good ' Website: (None)'55end5657acl = @s3.get_bucket_acl(bucket: bucket.name)58print_good " Owner: #{acl.owner.display_name}"59print_good ' Permissions:'60acl.grants.each do |i|61grantee = i.grantee.type == 'CanonicalUser' ? 'User' : i.grantee.type62grantee << " '#{i.grantee.display_name}'"63grantee << " (#{i.grantee.email_address})" unless i.grantee.email_address.nil?64grantee << " (#{i.grantee.uri})" unless i.grantee.uri.nil?65print_good " #{grantee} granted #{i.permission}"66end67print_status ''68end6970def run71region = datastore['REGION']7273@s3 = Aws::S3::Client.new(74region: 'us-west-2', # This doesn't actually filter anything, but75# it's still required. Thanks AWS. :-(76access_key_id: datastore['ACCESS_KEY_ID'],77secret_access_key: datastore['SECRET_ACCESS_KEY']78)7980buckets = @s3.list_buckets.buckets81if buckets.empty?82print_status 'No buckets found.'83return84end8586print_good "Found #{buckets.count} buckets."87if region.nil?88buckets.each do |bucket|89describe_s3_bucket(bucket)90end91else92print_good "Listing buckets that match REGION '#{datastore['REGION']}':"93buckets.each do |bucket|94if @s3.get_bucket_location(bucket: bucket.name).location_constraint.starts_with? region95describe_s3_bucket(bucket)96end97end98end99print_status 'Done.'100rescue StandardError => e101handle_aws_errors(e)102end103end104105106