Sicherheits- und Stabilitaetskorrekturen nach vollstaendiger Pruefung

- Login-Sperre war umgehbar: clientKey() vertraute dem Header CF-Connecting-IP.
  Bei Cloudflare war das sicher (CF ueberschreibt ihn), auf dem eigenen Server nicht:
  der Ursprungsserver ist auch direkt unter seiner IP erreichbar, dort konnte der
  Header frei gesetzt und die 5-Versuche-Sperre komplett ausgehebelt werden
  (nachgewiesen). Jetzt req.ip hinter trust proxy.
- Absturzsicherheit: Express 4 faengt Fehler aus async-Handlern nicht ab, eine
  einzige fehlerhafte Anfrage konnte den ganzen Dienst beenden. wrap() um alle
  Handler, zentraler Fehler-Handler, unhandledRejection/uncaughtException-Netz.
- Sicherheits-Header (X-Content-Type-Options, X-Frame-Options, Referrer-Policy,
  Permissions-Policy, HSTS) wurden bisher nur ueber die Datei _headers gesetzt,
  die auf dem eigenen Server wirkungslos ist. Jetzt im Express-Server.
- x-powered-by abgeschaltet.
- Datenschutzerklaerung/AGB: nannten Cloudflare als Hoster und eine Cloudflare-D1-
  Datenbank. Jetzt korrekt netcup (Rechenzentrum Nuernberg) als Hoster, Cloudflare
  als vorgeschaltetes CDN mit Drittlandhinweis.
This commit is contained in:
2026-08-05 22:33:31 +02:00
parent 61729d4f12
commit d6489f787a
6 changed files with 109 additions and 25 deletions
+14 -1
View File
@@ -12,8 +12,21 @@ const LOCKOUT_MINUTES = 15;
const INACTIVITY_MS = 24 * 60 * 60 * 1000;
const SESSION_MAX_AGE_MS = 24 * 60 * 60 * 1000;
/* Schlüssel für die Fehlversuchs-Zählung (Login-Sperre).
SICHERHEITSKORREKTUR 05.08.2026: Vorher stand hier `req.headers["cf-connecting-ip"] || req.ip`.
Bei Cloudflare war das sicher, weil Cloudflare diesen Header selbst setzt und einen vom Client
mitgeschickten überschreibt. Auf dem eigenen Server gilt das NICHT mehr: der Ursprungsserver ist
(nachgewiesen am 05.08.) auch direkt unter seiner IP erreichbar, also an Cloudflare vorbei — ein
Angreifer konnte dort bei jedem Versuch einen anderen `CF-Connecting-IP`-Wert mitschicken und so
die 5-Versuche-Sperre komplett aushebeln (unbegrenztes Durchprobieren des Owner-Codes).
`req.ip` ist hier nicht fälschbar: `app.set("trust proxy", 1)` in index.js lässt Express genau
eine Proxy-Ebene (den lokalen Caddy) vertrauen, und Caddy hängt die echte Verbindungs-IP hinten
an `X-Forwarded-For` an — ein vom Client vorgetäuschter Wert landet weiter vorne und wird
ignoriert. */
export function clientKey(req) {
return req.headers["cf-connecting-ip"] || req.ip || "unknown";
return req.ip || req.socket?.remoteAddress || "unknown";
}
function timingSafeEqual(a, b) {