AWS Pentesting

S3

Hunting

You can reach S3 buckets via a web interface regardless of whether or not access is permitted. The URL formats are:

http://<bucketname>.s3.amazonaws.com
http://s3.amazonaws.com/<bucketname>

A couple of things worth keeping in mind for creating tooling around hunting for buckets:

  • Names must be >= 3 && <= 63 characters long
  • Names can contain lowercase letters, numbers and hyphens
  • Names consist of labels, which can be separated with periods. Each label must start and end with a lowercase letter or number
  • Bucket names can't be formatted as an IP address

Response codes

404 - bucket doesn't exist
403 - bucket exists but you don't have access
200 - bucket exists and is accessible

If a bucket returns a 403, you can still do some things with the S3 API (this does cost money per 1000 requests, so be sparing when hunting for buckets on a large scale).

AWS CLI

It's also worth trying things out with the CLI. It's also important to remember to try reading and writing (sometimes you can do one and not the other).

List files in bucket:

aws s3 ls s3://bucketname

Copy a file to a bucket:

aws s3 cp canary.txt s3://bucketname

Google Dorks

site:s3.amazonaws.com example
site:s3.amazonaws.com example.com
site:s3.amazonaws.com example-com
site:s3.amazonaws.com com.example
site:s3.amazonaws.com com-example

List the size and name of s3 buckets your credentials can access

Be sure to change the region.

#!/bin/bash
aws_profile=('default' 'otherprofile');

#loop AWS profiles
for i in "${aws_profile[@]}"; do
  echo "${i}"
  buckets=($(aws --profile "${i}" --region us-east-2 s3 ls s3:// --recursive | awk '{print $3}'))

  #loop S3 buckets
  for j in "${buckets[@]}"; do
  echo "${j}"
  aws --profile "${i}" --region us-east-2 s3 ls s3://"${j}" --recursive --human-readable --summarize | awk END'{print}'
  done

done

Resources:
https://craighays.com/bug-bounty-hunting-tips-3-kicking-s3-buckets/
https://blog.securitybreached.org/2018/09/24/subdomain-takeover-via-unsecured-s3-bucket/
https://devops.stackexchange.com/questions/2241/view-all-aws-s3-buckets-and-list-each-buckets-storage-used

Pacu

Set the keys

This will use the keys in ~/.aws/credentials from the default region:

import_keys default

Set the region

This will set the region to us-east-2:

set_regions us-east-2

Verify credentials

whoami

List modules

ls

Run module

This will run a module to enumerate permissions the current account has:

run iam__enum_permissions

Post Exploitation

This is a good place to start if you've got credentials or you've compromised a system that's hosted on AWS.

Set credentials for AWS cli

Add the credentials to ~/.aws/credentials. It should look something like this:

[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token=AQoDYXdzEJr...<remainder of security token>

Make sure to set the proper region as well in ~/.aws/config, which you can get using this command on the compromised instance:

curl http://169.254.169.254/latest/dynamic/instance-identity/document

An alternative with wget:

wget -O - -q http://169.254.169.254/latest/dynamic/instance-identity/document

It should look something like this (the region will obviously vary):

[default]
region = us-east-2

Search for aws keys in bash scripts

find / -name '*.sh' -exec grep -HE "([^A-Z0-9]|^)AKIA[A-Z0-9]{12,}" {} \;

Resource:
https://twitter.com/omespino/status/1242977678329819141?s=20

Search for access keys with grep

Access key:

grep -RP '(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])' * 2>/dev/null

Secret access key:

grep -RP '(?<![A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])' * 2>/dev/null

Resource:
https://gist.github.com/hsuh/88360eeadb0e8f7136c37fd46a62ee10