Bremsen, Sperren und CSP: die offenen Punkte schliessen

S3: Aus der Kontosperre wird eine Wartezeit. Die alte Sperre wies auch das
richtige Passwort ab — wer die Adresse eines Administrators kannte, konnte
ihn alle 15 Minuten neu aussperren. Jetzt bleiben vier Fehlversuche
folgenlos, danach verdoppelt sich die Wartezeit bis zu einer Minute. Der
Besitzer kommt spaetestens nach einer Minute hinein, ein Fremder bekommt
einen Versuch pro Minute. Ausgewertet wird sie vor der Passwortpruefung,
damit ein ohnehin abgewiesener Versuch keine 128 MiB kostet.

S4: Drei Stufen statt einer. Die Bremse je Absender liest
X-Forwarded-For nur noch mit TRUST_PROXY=true — ohne Proxy waehlt den Wert
jeder Aufrufer selbst, und eine so umgehbare Bremse ist eine Behauptung.
Dazu die Wartezeit je Konto, die an der Datenbank haengt, und eine
Obergrenze fuer die ganze Installation: 60 Passwortpruefungen und 120
Rueckmeldungen je Minute. Die letzte Stufe ist die einzige, die sich nicht
ueber Kopfzeilen umgehen laesst, und sie schuetzt den Speicher.

CSP: Eine vollstaendige Policy mit Nonce je Anfrage, strict-dynamic,
default-src self, object-src none, base-uri und form-action self. Skripte
ohne den Nonce dieser Anfrage laufen nicht mehr. Zwei Lockerungen bleiben
und stehen begruendet in der Doku: style-src erlaubt unsafe-inline, weil
ein Nonce keine style-Attribute deckt, und media-src erlaubt https, weil
der Typ Video ausdruecklich Direktlinks annimmt.

Protokoll: Sicherheitsereignisse als JSON auf die Standardausgabe —
Fehlversuche, OIDC-Verknuepfungen samt abgelehnten, Vergabe von
Administratorrechten. Ohne Passwoerter, Token und Adressen.

Refs #20
This commit is contained in:
Florian Wilde
2026-08-24 01:43:00 +02:00
parent 1e0d04d0db
commit 367d9c540b
11 changed files with 487 additions and 78 deletions
+9 -1
View File
@@ -291,7 +291,7 @@ sie eintragen.
| --- | --- | --- |
| `X-Forwarded-Proto` | erkennt, dass die Verbindung über HTTPS läuft | Der Sitzungs-Cookie wird ohne `Secure` gesetzt und ginge auch über eine unverschlüsselte Verbindung mit |
| `X-Forwarded-Host` | die aufgerufene Domain — für mehrere Domains und für die Anmeldung | Kurz-URLs unter Zweitdomains werden nicht zugeordnet |
| `X-Forwarded-For` | Absender für die Bremse gegen Durchprobieren | Alle Aufrufe zählen als derselbe Absender |
| `X-Forwarded-For` | Absender für die Bremse gegen Durchprobieren | Die Bremse je Absender entfällt; Wartezeit je Konto und Obergrenze der Instanz greifen weiter |
Für ein reines nginx (ohne NPM) heißt das:
@@ -305,6 +305,14 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Bei **Traefik** und **Caddy** ist nichts zu tun — beide setzen die Kopfzeilen
von sich aus.
> **`TRUST_PROXY=true` erst setzen, wenn der Proxy wirklich steht.** Die
> Anwendung liest `X-Forwarded-For` nur mit dieser Angabe. Ohne Proxy könnte
> die Kopfzeile jeder Aufrufer selbst wählen und sich damit beliebig viele
> Anmeldeversuche verschaffen — eine Bremse, die sich so umgehen lässt, wäre
> eine Behauptung. Zwei Bremsen wirken unabhängig davon immer: die Wartezeit
> je Konto und die Obergrenze für die ganze Installation. Näheres in
> [docs/sicherheit.md](docs/sicherheit.md).
### Größe der Uploads
PDFs und Bilder gehen durch den Proxy. nginx bricht Anfragen oberhalb von