Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/cloud/aws/enum_s3.rb
19500 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'aws-sdk-s3'
7
8
class MetasploitModule < Msf::Auxiliary
9
def initialize(info = {})
10
super(
11
update_info(
12
info,
13
'Name' => 'Amazon Web Services S3 instance enumeration',
14
'Description' => %q{
15
Provided AWS credentials, this module will call the authenticated
16
API of Amazon Web Services to list all S3 buckets associated
17
with the account
18
},
19
'Author' => ['Aaron Soto <[email protected]>'],
20
'License' => MSF_LICENSE,
21
'Notes' => {
22
'Stability' => [CRASH_SAFE],
23
'SideEffects' => [IOC_IN_LOGS],
24
'Reliability' => []
25
}
26
)
27
)
28
29
register_options(
30
[
31
OptString.new('REGION', [false, 'AWS Region (eg. "us-west-2")']),
32
OptString.new('ACCESS_KEY_ID', [true, 'AWS Access Key ID (eg. "AKIAXXXXXXXXXXXXXXXX")', '']),
33
OptString.new('SECRET_ACCESS_KEY', [true, 'AWS Secret Access Key (eg. "CA1+XXXXXXXXXXXXXXXXXXXXXX6aYDHHCBuLuV79")', ''])
34
]
35
)
36
end
37
38
def handle_aws_errors(error)
39
if error.class.module_parents.include?(Aws)
40
fail_with(Failure::UnexpectedReply, error.message)
41
else
42
raise error
43
end
44
end
45
46
def describe_s3_bucket(bucket)
47
print_good " Name: #{bucket.name}"
48
print_good " Creation Date: #{bucket.creation_date}"
49
print_good " # of Objects: #{@s3.list_objects_v2(bucket: bucket.name).contents.length}"
50
print_good " Region: #{@s3.get_bucket_location(bucket: bucket.name).location_constraint}"
51
52
begin
53
print_good " Website: /#{@s3.get_bucket_website(bucket: bucket.name).index_document.suffix}"
54
rescue Aws::S3::Errors::NoSuchWebsiteConfiguration
55
print_good ' Website: (None)'
56
end
57
58
acl = @s3.get_bucket_acl(bucket: bucket.name)
59
print_good " Owner: #{acl.owner.display_name}"
60
print_good ' Permissions:'
61
acl.grants.each do |i|
62
grantee = i.grantee.type == 'CanonicalUser' ? 'User' : i.grantee.type
63
grantee << " '#{i.grantee.display_name}'"
64
grantee << " (#{i.grantee.email_address})" unless i.grantee.email_address.nil?
65
grantee << " (#{i.grantee.uri})" unless i.grantee.uri.nil?
66
print_good " #{grantee} granted #{i.permission}"
67
end
68
print_status ''
69
end
70
71
def run
72
region = datastore['REGION']
73
74
@s3 = Aws::S3::Client.new(
75
region: 'us-west-2', # This doesn't actually filter anything, but
76
# it's still required. Thanks AWS. :-(
77
access_key_id: datastore['ACCESS_KEY_ID'],
78
secret_access_key: datastore['SECRET_ACCESS_KEY']
79
)
80
81
buckets = @s3.list_buckets.buckets
82
if buckets.empty?
83
print_status 'No buckets found.'
84
return
85
end
86
87
print_good "Found #{buckets.count} buckets."
88
if region.nil?
89
buckets.each do |bucket|
90
describe_s3_bucket(bucket)
91
end
92
else
93
print_good "Listing buckets that match REGION '#{datastore['REGION']}':"
94
buckets.each do |bucket|
95
if @s3.get_bucket_location(bucket: bucket.name).location_constraint.starts_with? region
96
describe_s3_bucket(bucket)
97
end
98
end
99
end
100
print_status 'Done.'
101
rescue StandardError => e
102
handle_aws_errors(e)
103
end
104
end
105
106