From 182ef04cc5ed54bc2fb17e2bde9511c263467eec Mon Sep 17 00:00:00 2001 From: Stefan Hacker Date: Thu, 16 Apr 2026 12:53:13 +0200 Subject: [PATCH] Harden security, polish admin UI and document Windows WebDAV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - helmet, express-rate-limit (login/setup/customer-auth/me-password) - Constant-time login (bcrypt always runs against a dummy hash on miss) - Cookie secure flag follows req.protocol; trust proxy is env-gated to prevent X-Forwarded-For spoofing on direct exposure - Drop SVG from accepted logo types (same-origin XSS) and resolve the served logo path against LOGO_DIR as defense in depth - Self-service /me/password endpoint plus header button; bumps minimum password length to 8 across backend, prompts and edit modal - Multer 1.x → 2.x for current security backports - Customer edit modal replaces stacked prompts; user role is now an inline dropdown with a confirm-and-revert flow - Windows .reg helper plus README section for Basic-Auth-over-HTTP and the http:// vs \\HOST@PORT\DavWWWRoot\ mapping syntax Co-Authored-By: Claude Opus 4.6 (1M context) --- .env.example | 9 ++ README.md | 43 +++++++-- package.json | 4 +- public/admin/index.html | 135 +++++++++++++++++++++++----- src/auth.js | 20 ++++- src/server.js | 83 ++++++++++++++--- windows/enable-webdav-basicauth.reg | 12 +++ 7 files changed, 263 insertions(+), 43 deletions(-) create mode 100644 windows/enable-webdav-basicauth.reg diff --git a/.env.example b/.env.example index 8401e69..a51110e 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,12 @@ # Ports, auf denen die Services vom Host erreichbar sind. APP_PORT=3500 WEBDAV_PORT=1900 + +# Auf "true" setzen, wenn die App hinter einem Reverse-Proxy (nginx/Traefik/Caddy) +# läuft, der X-Forwarded-For/-Proto setzt. Sonst bitte aus lassen, sonst können +# Angreifer per gespooften X-Forwarded-For die Rate-Limits umgehen. +# TRUST_PROXY=true + +# Erzwingt das "Secure"-Flag auf Session-Cookies (für HTTPS-only Setups). +# Wenn TRUST_PROXY=true gesetzt ist, wird das automatisch erkannt. +# SECURE_COOKIES=true diff --git a/README.md b/README.md index 36e6f5b..79c6c13 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,41 @@ Der WebDAV-Container (Debian Apache) beobachtet das Verzeichnis via `inotifywait ## WebDAV-Zugriff -- macOS Finder: `Gehe zu → Mit Server verbinden → http://HOST:1900/` -- Windows: Netzlaufwerk hinzufügen → `http://HOST:1900/` -- Linux / KDE Dolphin: `webdav://@HOST:1900/` -- Write-Rechte umfassen: `PUT`, `DELETE`, `MKCOL`, `MOVE`, `COPY`, `PROPPATCH`, `LOCK`, `UNLOCK`. -- In Dolphin löscht **Shift+Entf** direkt (umgeht den nicht existierenden WebDAV-Papierkorb). +- **macOS Finder**: `Gehe zu → Mit Server verbinden → http://HOST:1900/` +- **Linux / KDE Dolphin**: `webdav://@HOST:1900/` +- **Windows**: siehe Abschnitt unten (einmalige Einrichtung nötig) + +Write-Rechte umfassen: `PUT`, `DELETE`, `MKCOL`, `MOVE`, `COPY`, `PROPPATCH`, `LOCK`, `UNLOCK`. +In Dolphin löscht **Shift+Entf** direkt (umgeht den nicht existierenden WebDAV-Papierkorb). + +### Windows als Netzlaufwerk verbinden + +Windows verweigert standardmäßig WebDAV via Basic Auth über HTTP und limitiert +Dateien auf 50 MB. Beides per Registry erlauben: + +1. [windows/enable-webdav-basicauth.reg](windows/enable-webdav-basicauth.reg) + per Rechtsklick → **Zusammenführen** (als Administrator) ausführen. +2. WebClient-Dienst (neu) starten: + + ```cmd + sc config WebClient start=auto + net stop WebClient + net start WebClient + ``` + +3. Verbinden — **HTTP-URL ist die saubere Variante** (eindeutig WebDAV, keine + SMB-Verwechslung). Beispiel mit `karlheinz`-Credentials, gemountet als `Z:`: + + ```cmd + net use Z: http://HOST:1900/frank-meier /user:karlheinz DEINPW /persistent:yes + ``` + + Im Explorer **„Netzlaufwerk verbinden"** → Adresse: + `http://HOST:1900/` bzw. `http://HOST:1900/frank-meier/`. + + Alternativ mit UNC-Syntax (intern dasselbe, etwas hakeliger): + `\\HOST@1900\DavWWWRoot\frank-meier\` — `@1900` und `\DavWWWRoot\` sind + dabei Pflicht, sonst landest du bei SMB Port 445. + +Wenn weiterhin „Ordner nicht gefunden" → meist ist der WebClient-Dienst nicht +gestartet oder das Registry-Merge wurde nicht als Administrator ausgeführt. diff --git a/package.json b/package.json index 12fb659..8f3b482 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "better-sqlite3": "^11.3.0", "express": "^4.21.0", "express-basic-auth": "^1.2.1", - "multer": "^1.4.5-lts.1", + "express-rate-limit": "^7.4.0", + "helmet": "^7.1.0", + "multer": "^2.0.0", "nanoid": "^3.3.7", "nodemailer": "^6.9.15" } diff --git a/public/admin/index.html b/public/admin/index.html index f81606e..72cb25d 100644 --- a/public/admin/index.html +++ b/public/admin/index.html @@ -160,6 +160,7 @@ .pill.archived { color: var(--text-dim); border-color: var(--border-strong); background: color-mix(in srgb, var(--text-dim) 10%, transparent); } tr.archived td:not(.cell-actions) { opacity: .55; } + select.role-select { padding: .25rem .5rem; font-size: .85rem; min-width: 9rem; } .small { font-size: .8rem; color: var(--text-muted); } .muted { color: var(--text-muted); } @@ -220,8 +221,8 @@
-
-
+
+
@@ -253,6 +254,7 @@ @@ -299,7 +301,7 @@

Benutzer anlegen

-
+
+ -
Max 2 MB. PNG, JPG, SVG, WEBP, GIF.
+
Max 2 MB. PNG, JPG, WEBP, GIF.
@@ -413,6 +415,36 @@
+ +
+