Security Baseline
Übersicht
Eine vollständige Referenz befindet sich in references/baseline.md (Abschnitte §0–§18, durchsuche mit ## N.). Diese Datei ist die Betriebsanleitung. Kernprinzip: Rigorosität an die Bedrohungsstufe anpassen, dann jeden Befund mit Beweisen belegen. Drei Gesetze: Vertraue niemals dem Client, vertraue niemals dem Code des Modells, vertraue niemals den Standardeinstellungen.
Wähle den Modus
| Anfrage | Modus | Lies in baseline.md |
|---|---|---|
| „Ein Projekt sicher planen/starten“, Agentenregeln schreiben | Plan | §0, §2, §3, §16 |
| „Diese App/Repo/PR überprüfen/auditieren“ | Code-Review | §1.3, §4–§11, §15.2 |
| „Meinen Server/Homelab/VPS auditieren“, „Ist er auf dem neuesten Stand?“ | Host-Audit | §3.3, §8.3, §12, §13 |
| „Wir wurden gehackt / haben einen Schlüssel verloren“ | Vorfall | §17, §8.2 |
Ein Host-Audit beinhaltet ein kurzes Code-Review jeder internetfähigen Anwendung, die Konten oder personenbezogene Daten speichert.
Schritt 1 – Klassifiziere die Stufe (immer zuerst, im Bericht angeben)
Anhand beobachtbarer Fakten entscheiden, nicht danach, was der Besitzer sagt:
| Stufe | Prädikat | Anwenden |
|---|---|---|
| T0 Spielzeug | Keine echten Benutzer oder Daten UND nicht aus dem Internet erreichbar (nur LAN oder hinter SSO) | §2, §8 |
| T1 Öffentlich, keine Konten | Internet-erreichbar, kein Login, keine personenbezogenen Daten gespeichert | T0 + §9, §10 |
| T2 Konten / Benutzerdaten | Jeglicher Login, jegliche personenbezogenen Daten (Namen, E-Mails, Gästelisten), jeglicher API-Schlüssel oder Token, den es speichert | Alles |
| T3 Geld / Personenbezogene Daten in großem Umfang / reguliert | Zahlungen, Gesundheitsdaten, Anmeldeinformations-Tresore, Finanzen, Daten von >1000 Personen, Kundenverträge | T2 + externe Überprüfung + §14 |
Ein Homelab-Host wird nach der höchsten Stufe von allem, was darauf läuft, bewertet. Ein Anmeldeinformations-Aggregator (Passwort-Manager, n8n, Home Assistant, Portainer, docker.sock-Inhaber) ist aufgrund des Schadensradius T3.
Schritt 2 – Beweise sammeln (nur lesen)
Führe die gebündelten Skripte über Bash aus. Auf einem entfernten Host über SSH streamen: ssh host 'bash -s -- --remote-digests' < scripts/audit-docker-host.sh und ssh host 'bash -s -- <project-dir>' < scripts/scan-code.sh.
bash scripts/audit-docker-host.sh --remote-digests– OS-Patches, Reboot-Flag, lauschende Sockets, Firewall, sshd, Benutzer/Berechtigungen/veröffentlichte Ports/docker.sock jedes Containers, geheimnisaussehende Umgebungsvariablen-NAMEN, Image-Aktualität (UP-TO-DATE / OUTDATED / local-build).bash scripts/scan-code.sh <project-dir>– grep Hinweise auf Secrets, Injection, XSS, Mass Assignment, client-seitig bereitgestellte Tenant-IDs, Fail-Open-Abfangen, schwache Kryptografie, Lockfiles, Dockerfile/Compose-Risiken, Routeninventar.
Führe dann aus, was Skripte nicht können:
- Reverse-Proxy-Inventar: Liste jeden öffentlichen Hostnamen, sein Ziel und ob eine Authentifizierung davor sitzt (NPM DB / Caddy / Traefik Labels). Admin-Oberflächen (§3.3 Liste) auf einem öffentlichen Hostnamen ohne SSO/Zugriffsliste = Befund.
- Externe Ansicht: Von außerhalb des LAN-Pfades
curl -sI https://<host>für Header (§10.2) und/.env,/.git/config,/admin,/apimit GET nur abfragen. - Autorisierungs-Trace für jede Anwendung der Stufe T2+: Benenne für jede Route die Autorisierungsprüfung und woher der Principal/Tenant-ID stammt (§4.3). Stelle die Frage aus §1.3.
- Proxy-Vertrauen: Wenn eine Anwendung
X-Forwarded-Forliest, überprüfe, welchem Hop sie vertraut ($proxy_add_x_forwarded_forhängt an; der erste Wert ist angreifergesteuert). - Passwortstärke pro Rolle: Finde für jede Rolle (Admin, Mitarbeiter, Freiwilliger, API/MCP-Token) heraus, wie ihr Secret gesetzt wird, einschließlich Seed, Legacy- und Migrationspfaden, die die normale Längenprüfung umgehen. Überprüfe die tatsächliche Länge von
.env-Werten mitawk -F= '{print $1, length($2)}', niemals durch Ausgabe. Ein schwaches Secret zusammen mit einer umgehbaren Ratenbegrenzung ist ein Befund, nicht zwei. - Versionen vs. Advisories: Vergleiche für jede internetfähige Anwendung die laufende Version mit der aktuellen Version und bekannten CVEs. Verwende eine Websuche nach den Sicherheitshinweisen des Produkts.
Host-Gate (die §16-Checkliste gilt pro Projekt; diese für einen Host verwenden)
- Jeder öffentliche Hostname ist gelistet, und jede Admin-Oberfläche (§3.3) hat SSO, eine Zugriffsliste oder VPN davor, oder ist nicht öffentlich
- Hypervisor, Docker, NPM/Proxy-Admin, Passwort-Tresor-Admin: niemals öffentlich
- Offene Registrierung deaktiviert auf jeder selbst gehosteten Anwendung, die es nicht benötigt (Vaultwarden, Open WebUI, Gitea, Immich, …)
- WAN-erreichbare Ports = nur 80/443 (+VPN). Docker-veröffentlichte Ports umgehen ufw: Überprüfe Router-Weiterleitungen und
DOCKER-USER - Proxy übergibt eine Client-IP, die von Anwendungen nicht getäuscht werden kann (§4.5, X-Forwarded-For)
- docker-Gruppenmitglieder aufgelistet; jeder ist Root-äquivalent
- Secret-Dateien Modus 600; keine weltlesbaren
.env/Schlüssel - OS gepatcht, kein ausstehender Reboot älter als 7 Tage; Images aktuell (Aktualitätstabelle)
- Backups wurden kürzlich ausgeführt und eine Wiederherstellung wurde getestet (§13.4)
Regeln für die Durchführung
- Standardmäßig nur lesen. Keine Schreibvorgänge, Neustarts, Updates, POSTs, die Daten ändern, Brute-Force-Angriffe oder Scannen von Hosts, die der Besitzer nicht besitzt.
- Niemals geheime Werte ausgeben. Nur den Variablennamen und die Datei:Zeile melden.
- Konfigurationsspeicher (DB-Konfigurationstabellen, JSON-Einstellungen,
docker inspect-Umgebungen) nur nach Schlüsseln und Längen durchsuchen:jq 'paths',SELECT key FROM …,awk -F= '{print $1, length($2)}'. Niemals eine gesamte Konfigurationszeile oder -datei ausgeben, um sie anzusehen: Sie enthält API-Schlüssel. - Änderungen (Updates, chmod, Konfigurationskorrekturen) erfolgen erst nach dem Bericht und nur, wenn der Anfänger danach gefragt hat. Für Updates befolge „Sicher aktualisieren" weiter unten.
Schritt 3 – Bericht (exakt diese Form)
- Umfang und Stufe: Was wurde untersucht, die Stufe und der einzeilige Grund.
- Urteil: Ein Satz – ausliefern / zuerst beheben / stoppen.
- Befunde, sortiert Kritisch → Niedrig. Jeder Befund hat: Titel,
BESTÄTIGT(du hast ihn reproduziert oder den genauen Code/Konfigurationspfad gelesen) oderHINWEIS(plausibel, nicht bewiesen), Beweis (Datei:Zeile, Befehl + Ausgabeauszug), Auswirkung in einem Satz, Behebung. - Aktualitätstabelle (Host-Audit): Komponente, laufende Version, neueste, Risiko der Aktualisierung.
- Abdeckung: Die §16-Gate-Abschnitte, die du geprüft hast, und die, die du nicht geprüft hast und warum. Stille ist kein Bestehen.
- Nächste Aktionen, nummeriert, zuerst den geringsten Aufwand/größtes Risiko.
Sicher aktualisieren („alles auf dem neuesten Stand halten")
- Bestätige, dass ein Backup existiert und aktuell ist (§13.4). Notiere die aktuelle Image-ID jedes Containers, damit ein Rollback mit
image: <repo>@<old digest>möglich ist. - Zustandslos = kein benanntes Volume oder Bind-Mount, in das die Anwendung schreibt, und keine Datenbank. Statische nginx-Seiten, gotenberg, flaresolverr sind zustandslos. Im Zweifelsfall als datentragend behandeln.
- Klassifiziere: datentragend oder schema-migrierend (Datenbanken, Immich, Paperless, Vaultwarden, Firefly, n8n, Home Assistant) → einzeln, lies zuerst die Release-Notes auf Breaking Changes. Zustandslos (statische nginx-Seiten, Tools) → in einem Rutsch.
- Überspringe niemals eine Datenbank-Hauptversion (postgres 15→17) mit
docker pull. Dazu ist ein Dump/Restore erforderlich. docker compose pull && docker compose up -dpro Projekt, dann überprüfe die Gesundheit: Container-Status, Logs auf Fehler und einen HTTP-Check der öffentlichen URL.- Lokale Builds (
local-build) aktualisieren, indem du mit--pullneu baust. OS-Pakete benötigen sudo; falls du keins hast, melde die Liste und das Reboot-Flag. - Wenn Pulls mit
429 toomanyrequestsfehlschlagen, anhalten. Frage nachdocker loginauf dem Host oder wiederhole nach 6 Stunden. Keine Schleife.
Häufige Fehler
| Fehler | Richtig |
|---|---|
| Alles als „Hoch" melden | Schweregrad = Ausnutzbarkeit × Stufe × Schadensradius |
| Einen Skripttreffer als Befund behandeln | Skriptausgabe ist ein HINWEIS, bis du den Code liest |
| „Container läuft als Root" ohne Überprüfung | Viele Images heben Berechtigungen im Entrypoint auf; überprüfe ps innerhalb |
| „Port 9000 ist offen" auf einem LAN-Host | Sage, wer ihn erreichen kann: nur LAN, WAN über Router-Weiterleitung, oder über Proxy |
| Stufe überspringen und eine statische Seite wie eine Bank auditieren | Stufe zuerst; T1 benötigt Header und Abhängigkeiten, nicht RLS |
Alles mit :latest auf einmal aktualisieren | Ein datentragender Dienst nach dem anderen, mit einem Rollback-Digest |
Behebung durch Deaktivieren der Steuerung (RLS aus, CORS *) | Behebe die Richtlinie, entferne sie niemals (§7.2) |