A free, open-source, gamified ICS/OT security training range. Spin up realistic industrial processes — a power substation, a water plant, building HVAC, a bottling line — and break into them with real tools (nmap, Metasploit, Wireshark). Watch the live SCADA schema react and the SOC alarms fire.
Built for hands-on learning and live demos: launch an attack → see the process move → see the alarm fire.
- 8 attack scenarios across the core OT protocols: Modbus, OPC-UA, BACnet, S7, IEC-104, plus a T0843 logic-implant lab on a real OpenPLC runtime and a Trisis-style SIS safety-bypass lab.
- Real targets, not screenshots — each lab is an isolated Docker stack running a protocol-faithful PLC with live process physics.
- Real tools — a built-in pentest workstation (noVNC desktop + embedded terminal) with Metasploit, nmap (+ OT NSE scripts), scapy, tshark/Wireshark and the protocol client libraries.
- Live SCADA / HMI — every scenario renders its own animated process schema (single-line diagram, gauges, alarm banner) that reacts to your writes.
- Real network detection — a sniffer sidecar sits in the PLC's own network namespace and dissects the wire protocol (Modbus function codes, S7 jobs, OPC-UA services, BACnet Who-Is, IEC-104 ASDUs, port scans, PLC engineering-UI sessions). The SOC panel shows packet evidence with MITRE ATT&CK for ICS technique references — not client-side guesswork.
- PCAP forensic challenge — the sniffer keeps a rolling
capture.pcapof suspicious traffic; download it from the SOC panel and analyze it in Wireshark. - Purple-team objectives — after the attack, restore power, close the firewall hole, and verify the blue-team side of the kill chain.
- Briefings & assessment reports — each lab opens with a threat-intel briefing (real-world incident, CVEs, MITRE mapping) and closes with a per-run scoring report (objectives, evidence, timestamps).
- Gamification — XP, levels, achievements, and a leaderboard.
- One lab at a time, started/stopped from the UI; verifiers auto-complete objectives by detecting the outcome — use any tool you like.
You need Docker Desktop (Engine 28+, Compose v2+) and ~10 GB free disk.
Linux / macOS / Windows (Git Bash or WSL):
git clone https://github.com/puffert/ot-lab.git
cd ot-lab
./setup.shsetup.sh generates a secret, builds the shared attacker image, starts the
platform and seeds the scenarios.
Then open http://localhost:5173, register an account, and pick a scenario.
Manual steps (if you prefer): see
manual.htmlormanual.md.
| Scenario | Protocol | Difficulty | What you do |
|---|---|---|---|
| Substation Breach | Modbus | Easy | Trip feeder breakers → total blackout → restore power (purple) |
| OPC-UA Water Plant | OPC-UA | Medium | Browse anon, poison the chlorine dosing |
| BACnet HVAC Takeover | BACnet | Medium | Who-Is → WriteProperty setpoint hijack |
| S7 Bottling Implant | S7comm | Expert | Read DB1, implant a value, CPU STOP |
| IEC-104 Sabotage | IEC 60870-5-104 | Medium | Industroyer-style: General Interrogation → C_SC_NA_1 breaker trips |
| Logic Implant (OpenPLC) | Modbus + HTTP | Medium | Stuxnet primitive: default creds → upload a logic program without the safety interlock (T0843) → tank overflow |
| SIS Override | Modbus ×2 | Expert | Trisis-style: brute the maintenance code, bypass the safety controller, rupture the vessel the SIS was protecting |
| Pivot Breach (flagship) | Modbus + IT/OT | Expert | Full kill-chain: recon DMZ → firewall misconfig → pivot → exploit → fix the firewall (purple), under Zeek + ELK SIEM |
Each scenario is mapped to real CVEs / MITRE ATT&CK for ICS techniques — see the scenario descriptions in-app and the manual.
Pivot Breach is the advanced lab: you start on a compromised corporate workstation, discover a misconfigured firewall that forwards Modbus into the OT zone, pivot to the PLC and attack it — while Zeek (IDS) and Elasticsearch + Kibana (SIEM) log every move. Open the SIEM from the lab page to watch the detections stream in.
┌─────────────┐ ┌──────────────────┐ ┌────────────────────┐
│ React SPA │◄─►│ FastAPI backend │◄─►│ PostgreSQL + WS │
│ (Vite/Boost)│ WS│ (async SA) │ └────────────────────┘
└─────────────┘ └────────┬─────────┘
│ docker.sock → spawns per-scenario compose stacks
▼
┌────────────────────────────────────────────────┐
│ scenario stack (ot_net) │
│ PLC ── HMI sidecar ── attacker ── verifier │
│ └─ sniffer (same netns: wire dissection, │
│ alerts → SOC panel, rolling capture.pcap) │
└────────────────────────────────────────────────┘
- Backend: FastAPI + SQLAlchemy async + PostgreSQL; WebSocket event push.
- Frontend: React 18 + Vite + Boosted 4.4 (Orange's Bootstrap fork).
- Per scenario: a protocol PLC (pymodbus / asyncua / bacpypes3 / snap7 / hand-rolled IEC-104 / real OpenPLC runtime), an HMI data sidecar (serves live JSON + the rolling pcap), a detection sniffer (scapy dissectors in the PLC's network namespace), an attacker workstation, and a verifier that awards XP on objective completion.
| Layer | Tech |
|---|---|
| Backend | FastAPI, SQLAlchemy async, PostgreSQL, JWT |
| Frontend | React 18, Vite, TanStack Query, Zustand, Framer Motion |
| Design | Boosted 4.4 (Orange brand) |
| Lab infra | Docker Compose; OpenPLC-style + pymodbus/asyncua/bacpypes3/snap7 |
| Tools | Metasploit, nmap (+ NSE), scapy, Wireshark/tshark |
- Scenarios → pick a card → Launch scenario → ▶ Start lab.
- Three tabs appear:
- SCADA / HMI — live process diagram.
- Detection / SOC — real packet-evidence alarms from the sniffer
(protocol function codes, scans, engineering-UI sessions) plus the
process-anomaly feed. Grab
capture.pcapthere for the forensic challenge. - Attacker workstation — embedded terminal (nmap / msfconsole / …). Every lab page also carries a collapsible threat-intel briefing (real incident, CVEs, MITRE mapping) and, after a run, an assessment report.
- Open GUI desktop (Wireshark) ↗ — full noVNC desktop (login
attacker/otlab).
Recon every target with nmap NSE, then exploit:
- Modbus →
msfconsole(auxiliary/scanner/scada/modbusclient) - OPC-UA →
asyncua(browse / write) - BACnet →
bacpypes3(Who-Is / WriteProperty) - S7 →
python-snap7(db_read/db_write/plc_stop) - IEC-104 → guided scripts (
04_interrogate.pyGI enumeration,05_trip.pyC_SC_NA_1) - OpenPLC → browser/
04_upload.py(program upload → compile → T0843)
Full commands and a run-of-show: manual.md.
| Port | Purpose |
|---|---|
| 5173 | Web UI |
| 8000 | API + WebSocket (set BACKEND_PORT in .env to move it, e.g. 8001) |
| 8088 | Live HMI telemetry + capture.pcap (running lab only) |
| 8081 | OpenPLC engineering web UI (logic-implant lab only) |
| 7681 | Embedded attacker terminal |
| 3000 | Full GUI desktop / Wireshark |
- One lab runs at a time — starting a new one stops the previous.
- Rebuild the attacker base after a Docker image wipe:
docker build -t otlab-attacker infrastructure/services/attacker - The logic-implant PLC compiles OpenPLC from source — the first
docker buildtakes several minutes; afterwards it's cached.
- More protocols (DNP3, Ethernet/IP)
- Multi-user / classroom mode
- Sniffer alert rules tunable per scenario (suricata-style rule packs)
Shipped recently: IEC-104 + SIS + OpenPLC logic-implant scenarios, real packet-evidence detection, PCAP forensic downloads, purple-team objectives, threat-intel briefings and per-run assessment reports.
Contributions welcome — see the scenarios under infrastructure/scenarios/ and
backend/seed.py.
OT Lab runs simulated industrial systems in isolated Docker networks. It is for education and authorized training only. Do not point these tools at systems you don't own or aren't authorized to test.
MIT — free for personal, educational and commercial use. OT Lab is not affiliated with Orange SA; it simply uses the open-source Boosted design system.
Built for cause-and-effect learning.


