Hands-on, genuinely runnable security labs — a companion to the Cipher iOS/watchOS course app.
Cipher teaches the concepts on your phone. CipherLabs is where you do them: each lab is a real, containerised environment you attack or defend from your own machine, with a written guide in the style of the SEED security labs — learning objectives, background, numbered tasks, questions to answer, and a submission checklist.
Every lab here was built and run on Apple Silicon before shipping. The red labs demonstrate the vulnerability and the fix; the blue labs give you a real incident to find.
This repository is deliberately vulnerable software. Read
SAFETY.mdfirst.The web apps contain real SQL injection, XSS, and CSRF; one lab runs an ARP spoofer; one boots a host with a live (contained) implant. All of it is safe only because of how it is run: every published port is bound to
127.0.0.1, every lab is on its own isolated Docker network, and nothing can reach or attack anything outside its own compose network. Do not run these on a server, a shared machine, or anything with a public IP.
| # | Lab | Level | Topic | Pairs with Cipher lesson |
|---|---|---|---|---|
| 01 | web-sqli |
Beginner | SQL injection → auth bypass, UNION data extraction, parameterized-query fix | SQL Injection |
| 02 | web-xss-csrf |
Beginner–Intermediate | Stored + reflected XSS, cookie theft, CSRF; output encoding, HttpOnly, SameSite, CSRF token |
Cross-Site Scripting (XSS), CSRF |
| 03 | network-sniff-spoof |
Intermediate | tcpdump sniffing, ARP-spoof MITM of cleartext creds, TLS contrast |
Network Poisoning & MITM |
| 04 | crypto-hashing |
Intermediate | Hash length-extension forgery of a secret-prefix MAC, then the HMAC fix | Hashing, Salting & Leaked Passwords |
| 05 | blue-log-triage |
Intermediate | Find a successful SSH brute-force buried in noise, pivot to the web exfil, write a detection | Log Analysis, Detection Engineering |
| 06 | blue-ir-forensics |
Intermediate–Advanced | Live-triage a compromised host: implant, exfil channel, all persistence, timeline | Incident Response Lifecycle |
Labs 01–04 are red (offensive, each ending in a defensive fix); 05–06 are blue (defensive). Every lab stands alone, but the order above is a sensible path.
- macOS on Apple Silicon (the author's machine) or any Linux/macOS host.
- Docker with Compose v2. The easiest is Docker Desktop, which ships
docker composebuilt in. Colima also works — see the note under Running a lab ifdocker composeis not on yourPATH. - A terminal,
curl, and a web browser. A couple of labs want two terminals; the guides say so.
All lab images build from official multi-arch bases (python:3.12-slim,
debian:bookworm-slim, nginx:alpine) and run natively on arm64 — no
emulation, nothing amd64-only. First build of a lab takes ~15–60 seconds;
afterwards it is instant.
Check your setup:
docker compose version # Compose v2.x
docker info # daemon reachable
./labctl list # should print the six labsUse labctl — you never have to remember compose paths.
./labctl list # show all labs with level, topic, and pairing
./labctl up 01 # build + start lab 01 (accepts 1, 01, or web-sqli)
./labctl status # what is running right now
./labctl shell 01 portal # open a shell in a lab container
./labctl logs 01 # follow logs
./labctl down 01 # stop and remove (containers, network, volumes)
./labctl reset 01 # down + delete built images, for a clean rebuildThen open the lab's guide — labs/<lab>/README.md — and work through it. Each
lab's SOLUTIONS.md has the answers and instructor notes; try not to peek.
A typical session:
./labctl up 01
open http://127.0.0.1:8101/ # (the guide tells you the URL)
# ... work through labs/01-web-sqli/README.md ...
./labctl down 01Colima users: if
docker composeis not on your hostPATH(Colima does not always install the plugin on the host),labctlwill automatically run Compose inside the Colima VM, since this repo lives under/Users, which Colima mounts. You can also justbrew install docker-composefor a host binary. Either way,./labctlworks.
The full version is in SAFETY.md. The guarantees:
- Loopback only. Every published port is bound to
127.0.0.1. Grep it:grep -rn '127.0.0.1:' labs/*/docker-compose.yml # every published port
- Isolated networks. Each lab has its own bridge network and subnet
(
10.9.1.0/24…10.9.6.0/24). Nonetwork_mode: host; no Docker socket mounted; noprivileged: true. The only elevated capabilities anywhere areNET_ADMIN/NET_RAWon lab 03's attacker container, which an ARP MITM needs. - No reaching out. No lab takes a target hostname or IP from you. The attack tools resolve their targets from Docker's internal DNS by compose service name and refuse to act outside the lab subnet. Nothing in here can attack anything beyond its own compose network.
- No real secrets. Every credential, key, and token is an obvious lab dummy.
If you ever find a way for a lab to affect something outside its own network,
that is a bug — see SAFETY.md.
CipherLabs/
├── README.md this file
├── SAFETY.md the safety model — read before running anything
├── LICENSE MIT
├── labctl the lab runner (./labctl list|up|down|reset|status|shell|logs)
└── labs/
├── 01-web-sqli/
│ ├── docker-compose.yml
│ ├── README.md the lab guide (SEED-style)
│ ├── SOLUTIONS.md answers + instructor notes
│ └── app/ the vulnerable application + Dockerfile
├── 02-web-xss-csrf/ webapp + attacker site + collector
├── 03-network-sniff-spoof/ server + victim + attacker (tcpdump, arpspoof)
├── 04-crypto-hashing/ signer + workbench (length-extension forge tool)
├── 05-blue-log-triage/ loggen + analyst (SQLite over the logs)
└── 06-blue-ir-forensics/ compromised victim + C2 collector
Each lab is self-contained: its own compose file, its own images built from
local Dockerfiles, its own guide and solutions.
- Each
SOLUTIONS.mdincludes an Instructor notes section: the expected stumbles, what to grade hardest, the deliberate design choices (including the places where the lab is honest about what it is not proving), and how to reset between groups. - The labs are deliberately honest about modern reality where the textbook
version is out of date — notably lab 02 on
SameSiteand browser cookie defaults, and lab 03 on what TLS does and does not hide. Those nuances are the graded centrepieces, not footnotes. - Reset any lab between cohorts with
./labctl reset <lab>.
MIT — see LICENSE. Copyright (c) 2026 at0m-b0mb.
The vulnerable code here exists for education. You are responsible for running it safely and for only practising these techniques on systems you own or are explicitly authorised to test.