flaws.cloud — Level 3¶
Vulnerability: AWS credentials committed to git history inside a publicly accessible S3 bucket
The Vulnerability Explained¶
This level combines two mistakes:
1. An S3 bucket open to any authenticated AWS user (same as level 2)
2. A .git directory sitting inside that bucket — and git history containing AWS keys that were later "deleted" but not rotated
The developer committed credentials, then deleted them in a follow-up commit. But git keeps full history forever. The current state of the repo looks clean. The history doesn't.
Step 1 — Download the Entire Bucket¶
aws s3 sync s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/ . --no-sign-request --region us-west-2
Breakdown:¶
| Part | What it does |
|---|---|
aws s3 sync |
Synchronise a source to a destination — downloads everything that's new or changed |
s3://level3-.../ |
Source: the S3 bucket |
. |
Destination: current local directory |
--no-sign-request |
Anonymous/unauthenticated — bucket is open to everyone |
--region us-west-2 |
Explicitly targets the bucket's region. Required if your default region differs |
sync vs cp --recursive: Both download everything. sync is smarter — it skips files you already have and only downloads differences. cp --recursive copies everything every time. For recon, either works; sync is faster on re-runs.
After this, your current directory contains all the bucket's files including the .git folder.
Step 2 — Spot the .git Directory¶
You'll see a .git/ directory. This is the entire git repository metadata — every commit, every version of every file, every piece of history.
Why is a .git in an S3 bucket? Someone probably ran aws s3 sync from a local git repo directory directly into S3. S3 just uploads everything it sees — including hidden folders like .git. It doesn't know or care what git is.
Why is .git dangerous? It's not just a log file. It contains the full object database of the repo — meaning you can reconstruct any version of any file from any point in history, even if that file was deleted or overwritten in the latest commit.
Step 3 — Read the Git Log¶
Shows the commit history, newest first:
commit b64c8dcfa8a39af06521cf4cb7cdce5f0ca9e526 (HEAD -> master)
Author: 0xdabbad00 <scott@summitroute.com>
Date: Sun Sep 15 09:11:06 2019 -0600
Oops, accidentally added something I shouldn't have
commit f52ec03b227ea6094b04e43f475fb0126edb5a61
Author: 0xdabbad00 <scott@summitroute.com>
Date: Sun Sep 15 09:10:43 2019 -0600
first commit
Read this like a stack — bottom is oldest, top is newest. "Oops, accidentally added something I shouldn't have" is a dead giveaway. The developer added credentials in the first commit, realised the mistake, and deleted them in the second commit.
The critical insight: The deletion in the second commit only removes the file from the current snapshot. The file still exists in the first commit's snapshot, permanently, in the git object store.
Step 4 — Go Back in Time to the Compromised Commit¶
This rewinds your working directory to exactly how the repo looked at that commit — including the deleted file with the credentials.
Breakdown:¶
| Part | What it does |
|---|---|
git checkout |
Switch to a different state of the repo |
f52ec03b... |
The commit hash — the unique ID of that specific commit (from git log) |
After running this, ls will show you the files that existed at that point in time, including whatever was "oops deleted".
What you find:¶
AWS Access Key ID and Secret Access Key — real credentials that give you access to the flaws.cloud AWS account.Step 5 — Use the Found Credentials¶
Enter the found Access Key ID and Secret Access Key. Then:
This lists all S3 buckets in the account — not just the one you're in. Because these are actual IAM user credentials for the account, not just scoped bucket access.
Output reveals the next level's bucket name.
Git Forensics Reference¶
git log # full commit history
git log --oneline # compact view, one line per commit
git log -p # show the diff/patch for each commit (very useful — shows exactly what was added/removed)
git show <hash> # show what changed in a specific commit
git checkout <hash> # rewind to that commit state
git checkout master # go back to latest
git diff <hash1> <hash2> # diff between two commits
git log -p is the most powerful for finding secrets — it shows the actual diff, so you can see lines that were added (green +) and removed (red -). Deleted credentials still show up as removed lines.
Why "Deleting" Credentials from Git Does Nothing¶
Think of git like this: every commit is a photograph. When you delete a file in a new commit, you're taking a new photo where the file isn't in frame. But the old photo still exists in the album.
The git object store (in .git/objects/) stores the actual file contents as blobs, referenced by their SHA1 hash. Deleting a file only removes the reference to it from the new commit's tree. The blob object stays in the store.
The only real fix:
1. Rotate (invalidate and replace) the credentials immediately
2. Then optionally clean git history with git filter-branch or git-filter-repo — but this only matters if you need to keep the repo; rotating the keys is what actually stops the attack
Vulnerability Summary¶
The flaws:
1. S3 bucket accessible to any authenticated AWS user (as in level 2)
2. .git folder uploaded to S3 accidentally (sync from a local repo)
3. Credentials committed to git, then "deleted" but not rotated
The attack chain:
1. Find bucket accessible with any AWS account
2. aws s3 sync — download everything including .git
3. git log — find the suspicious "oops" commit
4. git checkout <hash> — travel back in time
5. Read the credentials file
6. aws configure --profile flaws — load the creds
7. aws --profile flaws s3 ls — enumerate all buckets in the account
The fix:
- Never sync from a directory containing .git to S3 — use .s3ignore or explicitly exclude .git
- Rotate any credential the moment you suspect it was exposed, regardless of whether you "cleaned" the history
- Use IAM roles instead of long-lived access keys wherever possible