Drei echte Luecken gefunden und geschlossen: 1. Die 27 Server Actions verliessen sich allein auf proxy.ts. Jede prueft die Sitzung jetzt selbst und schlaegt gegen die Datenbank nach, ob das Konto noch gilt - damit lassen sich Sitzungen ueberhaupt erst widerrufen. 2. Der Anmelde-Endpunkt prueft die Herkunft des Formulars; vorher war Login-CSRF moeglich. 3. Content-Security-Policy mit Nonce je Anfrage und strict-dynamic. Dazu: npm audit ist ohne Befund (mysql2 und deepmerge-ts per overrides angehoben statt Prisma zurueckzustufen), eine Benutzerverwaltung fuer die Kommandozeile und docs/sicherheit.md mit allem, was bewusst offen bleibt - keine Rollen, keine Zwei-Faktor-Anmeldung. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Sicherheit
Dieses Dokument hält fest, was ProxLedger gegen die üblichen Angriffe tut – und was es nicht tut. Die Gliederung folgt den OWASP Top 10 (2021).
A01 – Fehlerhafte Zugriffskontrolle
src/proxy.tsschickt jede Anfrage ohne gültige Sitzung zur Anmeldung. Öffentlich sind nur die Anmeldung, die Agent-API (eigene Tokens), die Gesundheitsprüfung, die beiden Agent-Skripte und die Symbole.- Jede Server Action prüft zusätzlich selbst (
sitzungErforderlich()). Server Actions sind eigene Endpunkte; eine einzige Schutzschicht davor wäre zu wenig, falls der Musterausdruck im Proxy je danebengreift. - Die Prüfung geht in die Datenbank: Ein gesperrtes Konto oder ein Widerruf beendet laufende Sitzungen
sofort (
npm run benutzer -- sperren <email>), statt bis zum Ablauf des Tokens zu warten. - Die Anmeldung prüft den
Origin, damit keine fremde Seite jemanden unbemerkt in ein untergeschobenes Konto anmeldet (Login-CSRF). Für Server Actions erledigt das Next.js selbst.
Nicht vorhanden: Rollen. Wer angemeldet ist, darf alles. Für ein Werkzeug, das ein Systemhaus intern betreibt, ist das vertretbar – für mehrere Mandanten wäre es das nicht.
A02 – Kryptografische Fehler
- Passwörter: argon2id (
@node-rs/argon2), keine eigene Krypto. - Sitzungen: signiertes JWT (HS256) aus
APP_SECRET, 12 Stunden gültig, CookiehttpOnly,sameSite=laxundsecure, sobaldAPP_URLaufhttps://steht. - Zugangsdaten für SMTP und Webhooks liegen AES-256-GCM-verschlüsselt in der Datenbank
(
src/lib/geheimnisse.ts); der Schlüssel wird ausAPP_SECRETabgeleitet. - Agent- und Enrollment-Tokens werden nur als SHA-256-Hash gespeichert. Das ist hier richtig und nicht zu schwach: Die Tokens sind 32 Byte Zufall, es gibt nichts zu raten.
Wichtig: APP_SECRET ist der Generalschlüssel. Geht er verloren, sind alle Sitzungen ungültig und die
gespeicherten Zugangsdaten unlesbar. Er gehört in die Sicherung.
A03 – Injektion
- Datenbankzugriffe ausschließlich über Prisma mit gebundenen Werten; kein
$queryRawUnsafeim Projekt. - Ausgaben maskiert React selbst.
- Zusätzlich greift eine Content-Security-Policy mit frischem Nonce je Anfrage und
strict-dynamic(src/proxy.ts). Eingeschleustes<script>– etwa über einen manipulierten Hostnamen aus einer Proxmox-Ausgabe – läuft damit nicht. - Der Agent baut sein JSON mit einer eigenen Maskierung; Sonderzeichen aus Proxmox-Ausgaben sind als Testfall hinterlegt.
A04 – Unsicheres Design
- Push-Modell: Das Dashboard braucht keinen Zugang zu den Proxmox-Hosts. Es gibt keine gespeicherten root-Zugänge, die abhandenkommen könnten – die Hosts melden von sich aus.
- Der Agent sendet nur Statusangaben (Subscription, Version, Sockel, IPs). Keine Gastliste, keine Daten.
- Enrollment-Tokens sind befristet und in der Zahl der Nutzungen begrenzt.
A05 – Sicherheitsrelevante Fehlkonfiguration
- Kopfzeilen:
X-Content-Type-Options,X-Frame-Options: DENY,Referrer-Policy,Permissions-Policy,Strict-Transport-Security(next.config.ts) sowie die CSP aus dem Proxy. - Die Anwendung startet nicht mit zu kurzem
APP_SECRET. - Im Container läuft die Anwendung als unprivilegierter Benutzer; Anhänge werden mit Rechten 640 abgelegt.
- Fehlermeldungen nennen keine Einzelheiten: Bei der Anmeldung steht dieselbe Meldung für „Adresse unbekannt“ und „Passwort falsch“.
A06 – Verwundbare Komponenten
npm audit --omit=devmeldet keine bekannten Schwachstellen (Stand 18.09.2026).- Zwei Fassungen werden über
overridesangehoben:mysql2unddeepmerge-tskommen als Beiwerk von Prisma mit, obwohl wir Postgres nutzen. Ohne die Anhebung bliebe nur ein Rückschritt auf Prisma 6. - Die CI prüft bei jedem Push (#019).
A07 – Fehler bei Identifizierung und Authentifizierung
- Ratenbremse: fünf Anmeldeversuche je Kennung und Viertelstunde.
- Anmeldung wahlweise per Passwort oder OIDC (authentik, mit PKCE und
state). - Jede Anmeldung – erfolgreich oder nicht – landet im Audit-Log.
Nicht vorhanden: Zwei-Faktor-Anmeldung. Wer sie braucht, stellt OIDC davor und schaltet die Passwortanmeldung ab.
A08 – Datenintegrität
- Der Agent prüft vor dem Selbstaktualisieren, ob die geladene Datei wie ein Bash-Skript beginnt.
- Webhooks werden mit HMAC-SHA256 signiert, damit die Gegenstelle die Herkunft prüfen kann.
- Hochgeladene Rechnungen werden nicht dem gemeldeten Typ nach beurteilt, sondern am Dateianfang
geprüft (
%PDF-), auf 10 MB begrenzt und unter ihrer Prüfsumme abgelegt.
A09 – Protokollierung
- Audit-Log für Anmeldungen, Änderungen an Kunden, Rechnungen, Tokens, Kanälen und Warnregeln – einsehbar unter Einstellungen → Protokoll.
- Der Agent protokolliert auf dem Host über
loggerins Journal.
A10 – Server-Side Request Forgery
- Die einzige ausgehende Verbindung, die sich einstellen lässt, ist der Benachrichtigungs-Webhook. Er wird bewusst von einem Angemeldeten eingetragen und ist damit kein fremdgesteuerter Aufruf.
- Sonst ruft das Dashboard keine Adressen auf, die aus Daten stammen.
Was ein Betreiber selbst tun muss
- HTTPS davorschalten (Beispiele unter
deploy/reverse-proxy/) undAPP_URLaufhttps://setzen. APP_SECRETund die Datenbank sichern (deploy/backup.sh).- Das Dashboard nicht ins offene Internet stellen, wenn es nicht sein muss. Die Agent-API muss erreichbar sein, die Oberfläche nicht.
- Enrollment-Tokens nach dem Ausrollen widerrufen.