Cloud Storage Enumeration
Cloud storage services like Amazon S3 and Google Cloud Storage are widely used to store application data, backups and other files, and are often unintentionally exposed to the public. This section covers tools and techniques for discovering cloud storage buckets and determining what information or access they actually expose.
Google Cloud Storage Buckets
Google Cloud Storage (GCS) is Google’s object storage service and is commonly used by web applications, mobile applications and cloud infrastructure to store files and application data.
Just like AWS S3, the existence of a Google Cloud Storage bucket isn’t itself interesting from a security perspective. Many buckets intentionally contain publicly accessible application resources.
What we want to determine is whether the bucket exposes more information or permissions than intended.
This may include anonymous access to sensitive objects, bucket listing, excessive IAM permissions or storage locations that were never intended to be publicly discoverable.
Finding Bucket Names
The first step is normally discovering potential bucket names.
Bucket names may be based on:
Company nameDomain nameApplication nameProject nameEnvironmentFirebase projectCommon examples might look like:
exampleexample-prodexample-productionexample-backupsexample.appspot.comexample-app.appspot.comBucket names can appear in JavaScript, configuration files, mobile applications and API responses.
GCPBucketBrute
GCPBucketBrute from Rhino Security Labs can be used to enumerate Google Storage bucket names and test the access available to discovered buckets.
https://github.com/RhinoSecurityLabs/GCPBucketBruteNavigate to the tool:
cd ~/Hacking/Pentest_Tools/GCPBucketBruteA keyword can then be supplied:
sudo python3 gcpbucketbrute.py -k company_name -uThe keyword should generally be based on something associated with the target organisation, such as the company name, application name or domain.
GCPBucketBrute is useful because discovering that a bucket exists is only the first part of the problem. We also want to understand what level of access is available to it.
Checking a Bucket Manually
Google’s Cloud Storage JSON API can also be queried directly.
The following endpoint lists objects within a bucket where the caller has the required permission:
https://www.googleapis.com/storage/v1/b/<BUCKET NAME>/oThis gives us a very quick way of checking a discovered bucket.
For example:
https://www.googleapis.com/storage/v1/b/example.appspot.com/oThe response itself can provide useful information.
In my testing I generally interpret the responses as:
404 Bucket does not exist
401/403 Bucket exists, but anonymous access to the requested operation is not permitted
Object listing Bucket exists and the current caller is able to list objectsThe exact status code can vary depending on the request and Google’s access controls, so the important distinction is whether the bucket exists and whether the requested operation is permitted.
Google documents storage.objects.list as the permission required to list objects using this API.
Listing Bucket Contents
If object listing is permitted, the API response will contain information about the objects stored within the bucket.
This immediately gives us considerably more information to work with.
Interesting filenames may include:
backupconfigdatabaseexportcredentialsusersproductionprivatesecretWe can then investigate individual objects to determine whether sensitive information has actually been exposed.
Remember that the ability to list objects and the ability to retrieve an object are separate permissions. A bucket may expose one without necessarily exposing the other. Google documents these as storage.objects.list and storage.objects.get respectively.
Using gsutil
Google’s gsutil utility can also be used to interact with Cloud Storage.
Documentation:
https://cloud.google.com/storage/docs/gsutil_installTo attempt to list the contents of a bucket:
gsutil ls gs://example.appspot.comThis normally uses the currently authenticated Google identity, but it is also useful when determining whether the bucket permits the requested access without appropriate authorisation.
If access is granted, recursively listing the contents can provide a better picture of what information is stored within the bucket.
Modern Google Cloud environments may also use the equivalent gcloud storage commands:
gcloud storage ls gs://example.appspot.comGoogle currently documents gcloud storage ls as the command-line method for listing objects.
Retrieving the Bucket IAM Policy
If our current identity has sufficient permissions, the bucket’s IAM policy can be retrieved through the API:
https://www.googleapis.com/storage/v1/b/<BUCKET NAME>/iamFor example:
https://www.googleapis.com/storage/v1/b/example.appspot.com/iamThe policy can reveal which users, groups and service accounts have access to the bucket.
Pay particular attention to principals such as:
allUsersallAuthenticatedUsersallUsers represents anyone on the Internet, while allAuthenticatedUsers can provide access far beyond the organisation.
For example, granting allUsers the roles/storage.objectViewer role can make the bucket’s objects publicly readable and listable.
As with AWS, however, the complete configuration needs to be considered rather than treating a single IAM entry as the entire security picture.
Bucket ACLs
Older Google Cloud Storage configurations may also use ACLs.
Where the caller has sufficient permission, bucket ACL information can be retrieved through:
https://storage.googleapis.com/storage/v1/b/<BUCKET>/aclModern environments may use Uniform bucket-level access, in which case ACL operations are disabled and access is controlled through IAM instead.
This distinction is useful when testing because an ACL request failing does not necessarily mean that permissions cannot be assessed—it may simply mean that the bucket is using IAM exclusively.
Finding Buckets in Android Applications
Mobile applications are a particularly useful source of Google Cloud Storage bucket names.
Firebase and Google Cloud configuration values frequently survive application compilation and can therefore be identified after decompiling an APK.
One quick method is to recursively search the decompiled application for:
google_storage_bucketUsing PowerShell:
Get-ChildItem -Path .\app\ -Recurse |Select-String -Pattern "google_storage_bucket"We may find something similar to:
"google_storage_bucket": "example-mobile-app-production.appspot.com"This gives us a bucket name that can immediately be tested using the same techniques discussed above.
For example:
https://www.googleapis.com/storage/v1/b/example-mobile-app-production.appspot.com/oThis is one reason mobile application testing and cloud enumeration often overlap. Information embedded in the client application can expose cloud resources that were not obvious from the organisation’s website.
Don’t Stop at Bucket Discovery
Finding the bucket is only the beginning.
Once a bucket has been identified, determine what the current user can actually do.
Questions worth asking include:
Can I determine that the bucket exists?
Can I list its objects?
Can I retrieve individual objects?
Can I upload objects?
Can I overwrite objects?
Can I delete objects?
Can I retrieve its IAM policy?
Can I read its ACLs?
Do I have access when unauthenticated?
Do I have additional access using my supplied account?Different permissions have very different security implications.
A bucket containing intentionally public images is unlikely to be interesting.
A bucket containing private documents that can be downloaded anonymously is.
A bucket that allows an unauthenticated user to upload or overwrite application content could have significantly greater impact.
What Should We Look For?
Interesting Cloud Storage content may include:
Application configurationDatabase backupsAPI keysService-account informationCredentialsCustomer documentsInternal documentsSource codeEnvironment filesLogsExportsMobile application dataInfrastructure configurationBackupsDon’t report a bucket simply because it exists.
The important part is determining what information or capability is exposed and whether that exposure crosses the intended security boundary.
AWS S3 Buckets
Amazon Simple Storage Service (S3) is AWS’s object storage service. Applications use S3 buckets to store almost anything, including images, documents, backups, application data, log files and static website content.
From a penetration testing perspective, S3 becomes interesting when buckets or individual objects have been exposed unintentionally, permissions are too broad, or sensitive information has been uploaded to storage that was intended to be public.
A bucket being accessible from the Internet isn’t automatically a vulnerability. S3 is commonly used intentionally for public content. What we really want to establish is what an unauthenticated or low-privileged user can actually do with the bucket and what information is exposed.
Useful resources:
https://buckets.grayhatwarfare.com/
https://book.hacktricks.xyz/pentesting/pentesting-web/buckets/aws-s3#amazon-s3-bucketsFinding S3 Buckets
The first problem is normally identifying the bucket name.
Bucket names frequently contain information relating to the organisation, application or environment:
companycompany-backupscompany-prodcompany-productioncompany-devcompany-assetscompany-staticapplication-nameapplication-name-prodReferences to S3 buckets can also appear throughout an application’s client-side resources and configuration.
When assessing a web application, search JavaScript, HTML, API responses, configuration files and other client-side resources for strings such as:
amazonaws.coms3.amazonaws.coms3-.amazonaws.comMobile applications are another useful source because bucket names may be embedded in configuration files or application code.
We can also use search engines, certificate data, source-code repositories and other reconnaissance sources to identify references to an organisation’s storage infrastructure.
GrayHatWarfare
GrayHatWarfare maintains a searchable database of publicly exposed cloud storage buckets and files:
https://buckets.grayhatwarfare.com/Searching for the organisation name, domain name, application names and other unique identifiers may identify buckets or files that would otherwise be difficult to discover.
This can be particularly useful during external reconnaissance where we do not initially know the organisation’s bucket naming convention.
Checking Whether a Bucket Exists
Once we have a possible bucket name, we can attempt to access it through S3.
For example:
https://BUCKET.s3.amazonaws.com/Or:
https://s3.amazonaws.com/BUCKET/The exact response can provide useful information about whether the bucket exists and whether anonymous access is permitted.
An access-denied response should not immediately be discarded. It may confirm that the bucket exists even though directory-style listing is not available.
We can then continue testing individual objects or assess the bucket using the AWS CLI.
Anonymous Bucket Listing
One of the first things worth checking is whether the bucket allows its contents to be listed without authentication.
Using the AWS CLI:
aws s3 ls s3://BUCKET --no-sign-request--no-sign-request tells the AWS CLI not to use configured AWS credentials.
If the bucket permits anonymous listing, the returned object names can reveal considerably more information about the application or organisation.
For example:
backup/database/documents/exports/logs/production/users/Even when the individual objects are not sensitive, filenames and directory structures can reveal internal application functionality and naming conventions.
Recursively Listing Objects
If anonymous listing is permitted, recursively enumerate the bucket:
aws s3 ls s3://BUCKET --recursive --no-sign-requestFor a large bucket we may want to search the results rather than manually reviewing everything:
aws s3 ls s3://BUCKET --recursive --no-sign-request | grep -Ei 'backup|config|database|sql|password|secret|key|env|zip|tar|log'Interesting extensions may include:
.env.config.json.xml.yml.yaml.sql.db.sqlite.bak.zip.tar.gz.pem.key.pfx.logThe objective isn’t simply to prove that listing is possible. We want to determine whether the exposed objects contain information that creates meaningful security impact.
Accessing Individual Objects
A bucket may prevent directory listing while still allowing individual objects to be downloaded.
This distinction is important.
Knowing:
https://BUCKET.s3.amazonaws.com/does not necessarily tell us whether:
https://BUCKET.s3.amazonaws.com/backup.zipis accessible.
If object names are discovered elsewhere in the application, test those objects directly.
Using the AWS CLI:
aws s3 cp s3://BUCKET/path/to/file.txt - --no-sign-requestOr with HTTP:
curl https://BUCKET.s3.amazonaws.com/path/to/file.txtThis means “I can’t list the bucket” does not necessarily mean “the bucket contains nothing publicly accessible.”
Downloading Public Bucket Content
If anonymous listing and object retrieval are both allowed, content can be copied for further analysis:
aws s3 cp s3://BUCKET ./bucket-data/ --recursive --no-sign-requestOnly download information required for the assessment. Large storage buckets may contain significant amounts of data, so indiscriminately synchronising an entire bucket is usually unnecessary.
Authenticated Testing
During an AWS assessment we may have access to AWS credentials rather than testing anonymously.
First determine which identity we are currently using:
aws sts get-caller-identityWe can then test whether that identity can access the identified bucket:
aws s3 ls s3://BUCKETAuthenticated testing is particularly important because a bucket may correctly block anonymous users while granting excessive access to IAM users, roles or external AWS accounts.
The security question therefore becomes:
What can this particular AWS principal do with the bucket?
Bucket ACL
Where our current identity has permission, retrieve the bucket ACL:
aws s3api get-bucket-acl --bucket BUCKETReview the returned grants and determine which principals have access.
Historically, S3 ACLs were a common source of unintended public access. Modern AWS environments increasingly rely on bucket policies and IAM instead, but ACLs are still worth reviewing where they are enabled.
Bucket Policy
Retrieve the bucket policy:
aws s3api get-bucket-policy --bucket BUCKETBucket policies can be particularly interesting because they may grant access to:
EveryoneSpecific AWS accountsIAM usersIAM rolesAWS servicesExternal organisationsPay particular attention to statements containing broad principals such as:
"Principal": "*"However, the presence of "Principal": "*" does not automatically mean that the bucket is publicly exploitable. Conditions and S3 Block Public Access settings can significantly change the effective permissions.
The complete policy needs to be reviewed.
Is the Bucket Public?
AWS can report whether a bucket policy is considered public:
aws s3api get-bucket-policy-status --bucket BUCKETWe can also inspect the bucket’s public-access-block configuration:
aws s3api get-public-access-block --bucket BUCKETS3 Block Public Access provides several protections designed to prevent public ACLs and bucket policies from exposing data.
AWS applies the most restrictive applicable configuration between bucket, account and organisation-level controls, so simply seeing a permissive bucket policy does not necessarily mean the policy is effective.
What Permissions Matter?
When assessing an S3 bucket, think in terms of actions rather than simply “public” or “private”.
We may want to determine whether our current identity can:
List objectsRead objectsUpload objectsOverwrite objectsDelete objectsRead the bucket policyRead ACLsModify ACLsModify the bucket policyThese have very different security implications.
A publicly readable marketing image bucket may be completely intentional.
A publicly writable bucket is a very different situation.
Testing Upload Permissions
Where explicitly permitted by the engagement scope, test whether the current principal can upload an object using a harmless test file:
echo "pentest" > test.txt
aws s3 cp test.txt s3://BUCKET/test.txtFor anonymous testing:
aws s3 cp test.txt s3://BUCKET/test.txt --no-sign-requestIf the upload succeeds, verify the object and remove it afterwards:
aws s3 rm s3://BUCKET/test.txtWrite access can have considerably greater impact than read access, particularly where the bucket hosts application resources or static website content.
Do not overwrite or modify existing objects merely to demonstrate write access.
What Should We Look For?
Interesting S3 exposures may include:
Database backupsApplication backupsEnvironment filesConfiguration filesSource codeAPI keysAccess keysPrivate keysCertificatesCustomer documentsUser uploadsLogsInternal documentationInfrastructure configurationTerraform stateCI/CD artefactsFiles such as Terraform state can be particularly valuable because they may contain infrastructure information and sensitive values.
The impact of an exposed bucket should therefore be based on what is actually accessible, rather than simply reporting that an S3 bucket exists.
The interesting question is always:
What information or capability has been exposed to someone who shouldn’t have it?




