A self-contained Docker CTF that reproduces a 10-step red-team kill-chain against a fictional retailer, "ATB Market". You start at the perimeter (a handful of public web apps) and have to work inward: pop a shell, pivot across the internal network, loot credentials and escalate until you reach source control.
Built specially for DC8044.
Lab only. Every host, credential and vulnerability here is fictional and deliberately insecure. Run it on an isolated machine and never expose the ports.
- You only get the perimeter. With a normal start, the only things published on your host are the public web apps and Splunk (see table below). Everything else (Grafana, Zabbix, Harbor, Jenkins, the databases, the SSH hosts) lives on an internal Docker network. To touch them you must first get a foothold and pivot from inside, exactly like the real engagement.
- The web is clickable. Every web app is a real, navigable site: log in, click around, follow the links. You drive the HTTP/SQLi/LFI steps from your browser or your tooling; the non-web steps (ZBXD, SSH, Oracle, raw DBs) you run from the shell you land after the web-shell step.
- Reach the web apps only from "Your entry points" below. The internal web UIs (Grafana, Zabbix, Harbor, and the GitLab page that holds the flag) are not published; you get to them by pivoting from inside, not by exposing extra ports.
- One flag, in GitLab. There is a single flag, shown on the GitLab projects page at the final step. Every other step is proven by the access you gain, not by a flag string.
Linux / WSL2 / macOS with Docker Engine ≥ 24 and compose v2, ~8 GB RAM
(Splunk wants ~2 GB), ~6 GB disk, make / bash / curl / ssh.
make up # bootstrap keys -> build -> start the lab (first run pulls Splunk ~2.5 GB)
make ps # wait until everything is "running" (~60-90 s for DB seed + Splunk)
make down # stop make reset = stop + wipe volumes & logsPort already taken on your host (e.g. Burp on 8080)? Override any perimeter
port: WWW_PORT=18080 MOBAPP_PORT=18081 make up (also EDU_PORT,
SUPPLIER_PORT, OWA_PORT, SPLUNK_PORT; defaults in .env).
| Service | URL | What it is |
|---|---|---|
| ATB shop (Yii2) | http://localhost:8080 | online supermarket |
| Mobile app API | http://localhost:8081 | registration API + APK download |
| Staff LMS (Moodle) | http://localhost:8082 | employee e-learning |
| Supplier portal (SuiteCRM) | http://localhost:8083 | B2B supplier CRM |
| Corporate webmail (OWA) | http://localhost:8444 | Exchange / Outlook Web |
| Splunk (blue team) | http://localhost:8000 | SIEM, admin / changeme |
Yes, Splunk really is admin:changeme. That's not a challenge step - it's a wink
at the original infrastructure, where it was exactly that. Use it to watch
yourself (and to build detections): index atb.
Everything else is internal - no host port, and not listed here. Finding out what exists inside, and how to reach it, is part of the game.
- Recon. The public apps leak more than they should. Get the mobile app's API credential, and find the staff portal endpoint that discloses its config.
- SQL injection. Something in the shop's catalogue reaches the database unsanitised. Prove it and dump customers.
- Supplier foothold. Get a logged-in account on the supplier portal without a moderator ever approving you.
- File read. As a supplier, read files on the portal server. Its config holds secrets for half the company.
- Web-shell. Turn the portal into code execution despite the WAF in front of it. This is your foothold inside; everything after this is a pivot.
- Monitoring. Work out what monitors the portal box, get into it with what you already have, and become root on the monitoring server.
- Keys to everything. The monitoring server can talk to things you can't. Find the backups, find the key, reach the jump host.
- Databases. Loot the credentials scattered across registries, configs and shell history, and dump the retail and HR databases. Bind to the directory.
- Mail. Recover the supplier group mailbox password and read its inbox.
- Source. Own the source-control server - it only trusts the jump host.
Hints live in the world: page source, config comments, file-system notes, the monitoring host list, shell history and SSH configs. Follow them.
The goal here is to learn, so using the help is allowed. UA_Writeup.pdf
walks the full chain, and the ready scripts in attack/ drive each step;
together they let even a beginner finish the lab. If you are experienced, do it the
hard way: fully by hand, without the writeup or the scripts.
The chain is not one straight line. Recon forks into a standalone data dump and the foothold track; the mailbox falls from the perimeter without the deep pivot; and once you are inside, the last objectives open in parallel. Solid arrows are the path you take, dotted arrows are earlier loot a later step reuses. Node labels are the objectives only, no technique is spelled out.
flowchart TD
S1["1. Recon"]
subgraph PERIMETER["Perimeter (no pivot needed)"]
S2["2. SQL injection"]
S3["3. Supplier foothold"]
S4["4. File read"]
S5["5. Web-shell"]
S9["9. Mail"]
end
subgraph INTERNAL["Internal (reachable only by pivoting)"]
S6["6. Monitoring"]
S7["7. Keys to everything"]
S8["8. Databases"]
S10["10. Source"]
end
%% recon forks: a standalone dump, and the foothold track
S1 --> S2
S1 --> S3 --> S4 --> S5 --> S6 --> S7
%% file read opens the mailbox in parallel, no pivot required
S4 --> S9
%% deep access forks into two parallel objectives
S7 --> S8
S7 --> S10 --> FLAG["Flag"]
%% dotted = earlier loot reused by a later step (no tooling named)
S1 -. reused creds .-> S6
S1 -. reused creds .-> S8
S4 -. leaked secrets .-> S8
Every container ships structured JSON to Splunk (index atb). Whole-chain view:
index=atb | sort 0 _time | table _time host service event src_ip msg
Per-stage correlation searches ship in the atb_inputs app (ATB …); the SPL for
each step is in splunk/detections.md.
make up-devadditionally exposes every internal service on a host port (for debugging / building detections), seedocker-compose.dev.yml. Never give players this.make solve(pass the same*_PORT=overrides) runsattack/solve.py, the reference solver that drives all 10 steps and prints PASS/FAIL. It requiresmake up-dev.- Full walk-through and exact values:
docs/ctf-design.mdandSOLUTIONS.md(spoilers). docs/attack-chain.mdhas a copy-paste command block for every step. All 10 steps are verified working withmake solve.
- docs/ctf-design.md - topology, breadcrumbs, fixed values (spoilers)
- docs/attack-chain.md - each step in detail
- docs/asset-inventory.md - hosts, credentials, databases
- docs/apk-recon.md - extracting step 1's credential from the APK
- docs/network.md - network notes
- splunk/detections.md - SPL per stage
- DEPLOY.md - deployment / troubleshooting
