
Betreibt eine Flotte von absichtlich verwundbaren Web-/API-Anwendungen in isolierten Docker-Stacks für lokale Penetrationstests und die Validierung von Scanner-Ergebnissen anhand von Ground-Truth-Schwachstellenkatalogen.
Eine Flotte absichtlich verwundbarer Apps, auf die man Sicherheitswerkzeuge richten kann (crossfyre, Burp, ZAP, nuclei usw.). Dieser Ordner enthält keinen App-Quellcode, sondern nur Skelett-Definitionen und einen kleinen Manager. Jede App läuft als eigener isolierter Container-Stack, sodass nichts kollidiert.
Alles hier ist absichtlich verwundbar. Nur für lokale Tests. Setze diese Apps nicht dem Internet oder einem unsicheren Netzwerk aus. Alle Ports binden an
127.0.0.1.
docker compose up startet einen Container: vuln_apps_manager (die Steuerungsebene). Er startet von sich aus keine verwundbare App.apps/<name>/ definiert (ein app.yml-Manifest + eine compose.yml) und vom Manager als eigenes separates docker compose-Projekt ausgeführt.127.0.0.1 veröffentlicht. Datenbanken und interne Ebenen werden nie an den Host gebunden. Jeder Webdienst einer App tritt außerdem einem gemeinsamen vuln-net-Netzwerk bei, sodass ein im Container laufender Scanner sie per Namen erreichen kann (z. B. http://dvwa), ganz ohne Host-Port.cd vuln_apps
./vam start --all # ONE command: builds the manager, starts every light app,
# and runs each app's first-time setup automatically
./vam status # what's running + URLs
./vam stop --all # stop everything
Der einzelne Befehl ./vam start --all führt auch das einmalige Setup aus, das jede App benötigt (Datenbankerstellung bei DVWA, Installation bei bWAPP, Seed bei VAmPI), sodass jede App nutzbar ist, sobald sie running meldet – ohne manuelle Klicks auf /setup.php oder /install.php.
Soll der Manager als Live-Statusmonitor aktiv bleiben? Führe zuerst docker compose up -d aus und verwende dann ./vam ... wie oben.
./vam <cmd> ist nur ein Wrapper. Dasselbe ohne ihn:
docker compose run --rm vuln_apps_manager start --all
docker compose run --rm vuln_apps_manager status
| Befehl | Funktion |
|---|---|
./vam list | listet alle Apps, ihren Status und ihre URL auf |
./vam start <app...> | --all [--heavy] | startet App(s). --all überspringt ressourcenintensive Apps, außer mit --heavy |
./vam stop <app...> | --all | stoppt App(s) |
./vam restart <app...> | --all | startet App(s) neu |
./vam status | Statustabelle der Flotte |
./vam logs <app> [-f] | zeigt die Logs einer App (tail) |
./vam pull <app...> | --all | lädt Images vorab herunter |
./vam ports | Host-Port-Zuordnung + Portkonfliktprüfung |
./vam doctor | Umgebungs- und Port-Plausibilitätsprüfungen |
Beispiele: ./vam start juice-shop dvwa, ./vam start crapi --heavy, ./vam logs webgoat -f.
Alle URLs lauten http://127.0.0.1:<port> (nur Loopback).
| App | Port | Stack | Hinweise |
|---|---|---|---|
| juice-shop | 7001 | Node / Angular | moderne SPA + REST |
| dvwa | 7002 | PHP / MariaDB | DB wird beim Start automatisch erstellt; Login admin/password |
| webgoat | 7003 | Java | + WebWolf auf 7004 (OOB-Catcher) |
| vampi | 7005 | Python / Flask | OWASP API Top 10 |
| dvga | 7006 | Python / GraphQL | /graphql |
| bwapp | 7007 | PHP | wird beim Start automatisch installiert; Login bee/bug |
| log4shell | 7009 | Java / Spring | Blind-RCE -> OAST |
| crapi | 7010 | Node/Java/Python | ressourcenintensiv; mailhog auf 7011 |
| faultline | 8088 | SvelteKit/Rust/PG/Redis | von GitHub abgerufen (siehe unten) |
Reservierter Host-Port-Block: 7001-7099. ./vam ports zeigt die Live-Zuordnung und markiert jeden Konflikt.
Lege einen Ordner unter apps/ an:
apps/<name>/
app.yml # name, description, category, stack, url
compose.yml # the container(s): image, ports (127.0.0.1 only), any DB
setup.sh # optional: one-time init run after start (see below)
Regeln, die die Flotte sauber halten:
127.0.0.1:<freier 70xx-Port>.[vuln-net]. Füge KEIN separates Netzwerk pro Projekt hinzu – das schont Dockers Adresspool (bei zu vielen Netzwerken schlägt Docker mit "all predefined address pools have been fully subnetted" fehl).[default, vuln-net] und die Datenbank nur auf [default] (privat, kein Host-Binding). Gib jeder App einen eigenen DB-Dienst und ein eigenes Volume (nicht teilen). Deklariere vuln-net als external: true.apps/<name>/setup.sh hinzu. Der Manager führt sie nach start im Manager-Container aus (der auf vuln-net liegt und curl enthält), sodass er die App über den Dienstnamen erreichen kann, z. B. curl http://<service>/install.php.Das ist alles. Der Manager erkennt sie automatisch (./vam list).
Für eine App, deren Quellcode in einem Git-Repo liegt (wie faultline), überspringe compose.yml und trage stattdessen repo: (die Klon-URL) und compose: (den Compose-Pfad innerhalb dieses Repos) in app.yml ein. Der Manager klont das Repo beim ersten Start in apps/<name>/src/ (gitignoriert), sodass hier kein Quellcode mitgeliefert wird.
vulns/ enthält für jede App einen „Lösungsschlüssel“ (gegen welche Schwachstellen das jeweilige Ziel verwundbar sein soll), damit du Scanner-Ergebnisse gegen die Ground Truth prüfen kannst. Siehe vulns/README.md. Detaillierte lokale Kataloge gibt es für faultline und crapi; die Upstream-Apps verweisen auf ihre eigenen maßgeblichen Lösungsschlüssel.
crAPI nutzt Postgres + Mongo + drei App-Ebenen (~2 GB), daher überspringt --all sie. Starte sie explizit: ./vam start crapi --heavy. Der erste Start ist langsam; Registrierungs-OTP und Reset-Mails landen in mailhog unter http://127.0.0.1:7011.
faultline ist das eigene Full-Stack-Ziel von Clickswave. Sein Quellcode ist hier nicht mitgeliefert; der Manager klont das Repo beim ersten Start von github.com/clickswave/faultline:
./vam start faultline # clones the repo into apps/faultline/src/, then builds + runs it
Der erste Start baut das Projekt (Rust; langsam). Aktualisiere den Checkout später mit ./vam pull faultline. Danach öffne http://127.0.0.1:8088. Demo-Logins: [email protected] / password, [email protected] / admin.
docker compose down stoppt nur den Manager. Stoppe die Apps zuerst mit ./vam stop --all (es sind separate Projekte).