security: KRITISCH – Dashboard-Admin-Endpoints ohne Auth (Review-Befund o)
Fable-5-Review (n)+(o) beim Gegenlesen von server.py auf dem Pi: (o) KRITISCH: /api/ban, /api/unban, /api/toggle-registration, /api/create-invite, /api/run-stats sind über https://dashboard.steggi-matrix.work oeffentlich erreichbar und pruefen KEINEN Token (per curl belegt: App-eigene 400-Antwort ueber die oeffentliche URL). Fremde koennten Uta sperren oder offene Registrierung aktivieren; Hostname ist ueber CT-Logs auffindbar. Nicht blind gefixt (jede Auth-Ergaenzung legt Bernds Dashboard bis zur Token-Eingabe lahm -> kein Aussperren). Fertiger Plan mit zwei Wegen (Cloudflare Access / DASH_TOKEN) in docs/DASHBOARD_AUTH_HARDENING.md, ROADMAP M0 dringend, wartet auf Bernds Wahl. (n) LiveKit-Token-Route POST /api/livekit-token wurde von einer abgebrochenen Session bereits live in server.py gebaut (unprotokolliert). Geprueft + headless verifiziert (401/400/413/200, JWT-Signatur unabhaengig gegen livekit.yaml gueltig, Identitaet = gepruefte user_id). Server-Seite des M0-LiveKit-Punkts erledigt; Client-Umstellung + Rotation bleiben PC/Geraet (heiliger Call-Pfad). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+75
@@ -13,6 +13,42 @@ Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-04 – Fable-5-Review (n)+(o): LiveKit-Route live+geprüft, KRITISCHER Auth-Befund am Dashboard
|
||||
|
||||
**Erledigt:** Review-Pass über das, was seit (l)/(m) am Server dazugekommen ist –
|
||||
zwei neue Punkte (n)/(o) im Fable-5-Review-Abschnitt abgehakt (Details dort).
|
||||
- **(n):** Beim Gegenlesen von `server.py` gefunden, dass die geplante
|
||||
LiveKit-Token-Route `POST /api/livekit-token` von einer vorher abgebrochenen
|
||||
(unprotokollierten) Session **bereits live gebaut** wurde. Kritisch geprüft und
|
||||
headless verifiziert: Auth per whoami greift (ungültig→401), Body-Limit (413),
|
||||
gültig→200; das JWT unabhängig dekodiert und die **Signatur gegen `livekit.yaml`
|
||||
gegengerechnet – gültig**; Identität = geprüfte Matrix-user_id (kein Spoofing).
|
||||
Route ist gefahrlos additiv. Server-Seite des M0-LiveKit-Punkts damit erledigt;
|
||||
Client-Umstellung + Rotation bleiben PC/Gerät (heiliger Call-Pfad).
|
||||
- **(o) KRITISCH:** Derselbe Dashboard-Server hat für seine **Admin-Endpoints
|
||||
(`/api/ban`, `/api/unban`, `/api/toggle-registration`, `/api/create-invite`,
|
||||
`/api/run-stats`) KEINE Authentifizierung** und ist über
|
||||
`https://dashboard.steggi-matrix.work` **öffentlich erreichbar**. Belegt per
|
||||
`curl` (App-eigene 400-Antwort über die öffentliche URL, kein Login davor).
|
||||
Ein Fremder könnte damit Uta (jeden Nutzer) sperren oder die offene
|
||||
Registrierung am Homeserver aktivieren. Der Hostname ist über CT-Logs auffindbar.
|
||||
|
||||
**Offen/Nächster Schritt:** **Bernd muss entscheiden, WIE das Dashboard künftig
|
||||
authentifiziert** – Weg A (Cloudflare Access vor die Subdomain, kein Code, kein
|
||||
Aussperr-Risiko, empfohlen) oder Weg B (eigener `DASH_TOKEN` + `stats.html`-Prompt).
|
||||
Fertiger Plan mit beiden Wegen: `docs/DASHBOARD_AUTH_HARDENING.md`. Danach sofort
|
||||
umsetzbar + headless verifizierbar. Nicht blind gefixt, weil jede Auth-Ergänzung
|
||||
Bernds eigenes Admin-Panel bis zur Token-Eingabe lahmlegt („kein Aussperren") –
|
||||
das mitten in einer autonomen Session zu deployen ist die falsche Reihenfolge.
|
||||
|
||||
**Stolperfallen:** Ein Review, der sich auf den *geänderten* Endpoint (Diagnose,
|
||||
Disk-Fill) konzentriert, übersieht leicht die *unveränderten Nachbarn* in
|
||||
derselben Datei. Lehre: bei einem Sicherheits-Review einer Datei nicht nur den
|
||||
Diff prüfen, sondern die ganze Angriffsfläche der Datei (hier: alle Routen des
|
||||
`do_POST`-Handlers auf Auth abklopfen, nicht nur die neu berührte).
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-04 – Fable-5-Review (l)+(m): Diagnose-Endpoint hatte kein Größenlimit (gefixt)
|
||||
|
||||
**Erledigt:** Review-Pass über die zwei seit (k) dazugekommenen Arbeiten – als
|
||||
@@ -499,6 +535,45 @@ schließt den Review ab.
|
||||
`127.0.0.1:6167` (whoami-Basis). Python-Snippet (stdlib-HS256) fachlich
|
||||
korrekt (base64url ohne Padding, kompaktes JSON, HMAC-SHA256). Anmerkung:
|
||||
Der Plan setzt zusätzlich `nbf`/`name` – LiveKit akzeptiert beides, harmlos.
|
||||
- [x] **(n) LiveKit-Token-Route ist inzwischen LIVE auf dem Pi gebaut (bisher
|
||||
unprotokolliert) – geprüft und funktionsfähig, aber Client noch nicht
|
||||
umgestellt (2026-07-04).** Beim Review von `server.py` gefunden: Eine
|
||||
Vorsession hat die in `docs/LIVEKIT_TOKEN_MIGRATION.md` geplante Route
|
||||
`POST /api/livekit-token` bereits in `server.py` implementiert (whoami-Auth,
|
||||
stdlib-HS256-Minting aus `livekit.yaml`) – der CHANGES-Hook zeigt drei
|
||||
server.py-Edits um 04:33, Dienst-Neustart 04:34, aber kein PROGRESS-Eintrag
|
||||
(Session vor dem Protokoll abgebrochen). Headless verifiziert (127.0.0.1:8080
|
||||
UND öffentlich): ungültiger Matrix-Token → 401, fehlende Felder → 400, 5-KB-Body
|
||||
→ 413 (4-KB-Limit), gültiger Admin-Token → 200; das geminete JWT unabhängig
|
||||
dekodiert: iss=LKMatrixPi, sub/name/metadata = geprüfte user_id (kein Spoofing,
|
||||
Client kann Identität NICHT wählen), video-Grants wie im Client, exp−nbf =
|
||||
21600 s, **Signatur unabhängig gegen `livekit.yaml` gegengerechnet: gültig**.
|
||||
Die Route ist gefahrlos additiv (altes Client-Secret bleibt bis zur Rotation
|
||||
gültig, nichts bricht). **Offen bleibt:** Client-Umstellung
|
||||
(`livekit_token.dart`/`livekit_call_manager.dart`) + Secret-Rotation – beides
|
||||
weiterhin PC/Gerät (heiliger Call-Pfad), siehe Migrationsplan. Server-Seite des
|
||||
M0-LiveKit-Punkts ist damit erledigt.
|
||||
- [x] **(o) KRITISCHER Befund beim server.py-Review: die Admin-Endpoints des
|
||||
Dashboards haben KEINE Authentifizierung und sind öffentlich erreichbar
|
||||
(2026-07-04).** Der Review von (l) hatte nur das Diagnose-Endpoint auf
|
||||
Disk-Fill gehärtet – der viel größere Nachbar blieb unbemerkt:
|
||||
`https://dashboard.steggi-matrix.work` ist über Cloudflare offen aus dem
|
||||
Internet erreichbar, und `POST /api/ban`, `/api/unban`, `/api/toggle-registration`,
|
||||
`/api/create-invite`, `/api/run-stats` prüfen **keinen** Token. Belegt:
|
||||
`curl -X POST .../api/ban -d '{"user":""}'` liefert die App-eigene 400-Antwort
|
||||
`{"error":"Kein Nutzer angegeben"}` – identisch zu 127.0.0.1, also KEIN
|
||||
Cloudflare-Login davor. Damit könnte jeder Fremde Uta (jeden Nutzer) sperren
|
||||
oder die offene Registrierung am Homeserver aktivieren. Der Hostname ist über
|
||||
Certificate-Transparency-Logs praktisch auffindbar – „geheim" trägt nicht.
|
||||
**Bewusst NICHT blind gefixt:** Jede Auth-Ergänzung macht Bernds
|
||||
Browser-Dashboard funktionslos, bis er einen Token einträgt / Cloudflare Access
|
||||
einrichtet – das mitten in einer autonomen Session zu deployen sperrt ihn ohne
|
||||
Vorwarnung aus seinem eigenen Admin-Panel („kein Aussperren"). Fertiger,
|
||||
gegen den echten Code geschriebener Plan mit zwei Wegen (A: Cloudflare Access =
|
||||
Königsweg, kein Code; B: eigener `DASH_TOKEN` + `stats.html`-Prompt) liegt in
|
||||
`docs/DASHBOARD_AUTH_HARDENING.md`. **Braucht Bernds Wahl A oder B, dann
|
||||
sofortige Umsetzung + headless-Verifikation.** In ROADMAP M0 als dringender
|
||||
Punkt aufgenommen.
|
||||
|
||||
**Fazit:** Die Sonnet-5-Arbeit war handwerklich sauber; die zwei echten Lücken
|
||||
(verlorene Kommentare, fehlender Soft-Logout-Guard) hatte die abgebrochene
|
||||
|
||||
Reference in New Issue
Block a user