Härtung: REST-Query-Injection-Parität + TOFU-Fingerprint-Fallback
Dritter, sicherheitsfokussierter Deep-Dive-Durchgang ("maximale Sicherheit"):
- RestTransport.fetchFieldValues hatte dieselbe ungeschützte
String-Interpolation wie das SSH-Pendant aus dem vorigen Fix, nur als
URL-Query statt CLI-Zeile - beim ersten Fix übersehen. Jetzt
RFC-3986-konform percent-encoded.
- CertificateFingerprint.sha256 fiel bei Extraktionsfehlern auf einen
festen String "unbekannt" zurück statt echtem Fingerabdruck -
theoretisches TOFU-Pinning-Bypass-Fenster (zwei verschiedene,
extraktions-fehlschlagende Zertifikate hätten sich denselben
"Fingerabdruck" geteilt). Rückgabetyp optional, Extraktionsfehler
führt jetzt zu hartem Verbindungsabbruch statt Trust-Dialog.
Beide Fixes defensiv/gehärtet, nicht live exploitiert. Zugangsdaten-
Speicherung (Keychain) und BackupServices eigene Escaping-Logik
gegengeprüft - bereits korrekt. Build + alle 101 Unit-Tests grün.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -192,6 +192,51 @@ Produktentscheidung ist, keine reine Korrektur. Nur als Beobachtung vermerkt.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-17 (Nachtrag 2: "finale Test für maximale Sicherheit")
|
||||
|
||||
Dritter Durchgang, gezielt sicherheitsfokussiert: Zugangsdaten-Speicherung (Keychain, SavedRoutersStore),
|
||||
TOFU-Implementierung (Zertifikat/SSH-Hostkey), alle verbleibenden Stellen, die Text in Router-Befehle
|
||||
oder URLs interpolieren. Positiv: `KeychainService` speichert Passwörter korrekt im macOS-Keychain
|
||||
(nie Klartext/UserDefaults), `SavedRoutersStore`/`SavedRouter` enthalten kein Passwort-Feld,
|
||||
`BackupService.escapeForRouterOSScript` escapte bereits vor diesem Durchgang korrekt (unabhängig von
|
||||
Fund #5 — offenbar aus einem früheren Lockout-Vorfall gelernt), `SSHHostKeyFingerprint` hat keine
|
||||
Fallback-Schwäche. Zwei weitere Lücken gefunden und gehärtet (defensiv, nicht live exploitiert):
|
||||
|
||||
### 8. REST-Pendant zu Fund #5: ungeschützte Query-String-Interpolation
|
||||
**Status:** fixed (Build grün, nicht live exploitiert — aktuell nur mit hartkodiertem Wert aufgerufen)
|
||||
**Confidence:** hoch (dieselbe Bugklasse wie #5, nur im REST- statt SSH-Pfad)
|
||||
|
||||
`RestTransport.fetchFieldValues` baute den Query-String `"\(restPath)?\(whereField)=\(whereValue)"`
|
||||
ohne jede Kodierung — beim SSH-Gegenstück wurde das in Fund #5 bereits gefixt, das REST-Pendant
|
||||
dabei übersehen. Ein `whereValue` mit `&` hätte einen zusätzlichen Query-Parameter einschleusen
|
||||
können. Aktuell nur mit hartkodiertem `"no"` aufgerufen (kein Live-Exploit möglich), aber generische
|
||||
`RouterOSTransport`-Methode — Härtung für zukünftige Aufrufer mit echtem Nutzer-/Gerätetext.
|
||||
|
||||
**Fix:** `whereValue` wird jetzt RFC-3986-"unreserved characters"-only percent-encoded (strenger
|
||||
als `.urlQueryAllowed`, das `&`/`=`/`+`/`#` weiterhin durchlässt).
|
||||
|
||||
### 9. TOFU-Zertifikatsprüfung hatte einen Fallback-Konstante-Blindfleck
|
||||
**Status:** fixed (Build grün, Härtung — kein realistisch auslösbarer Live-Exploit gefunden)
|
||||
**Confidence:** mittel (theoretische Lücke im Code nachvollzogen, keine funktionierende PoC gebaut,
|
||||
da eine echte TLS-Handshake-Situation gebraucht würde, in der `SecTrustCopyCertificateChain` trotz
|
||||
abgeschlossenem Handshake leer zurückkommt — unüblich, aber laut Apple-API-Vertrag nicht ausgeschlossen)
|
||||
|
||||
`CertificateFingerprint.sha256(of:)` gab bei fehlgeschlagener Zertifikatsketten-Extraktion den festen
|
||||
String `"unbekannt"` statt eines echten Fingerabdrucks zurück. Da `CertificateTrustStore.isTrusted`
|
||||
Fingerabdrücke per exaktem String-Vergleich prüft, hätte das Vertrauen in EIN Zertifikat, dessen
|
||||
Extraktion fehlschlägt, automatisch JEDES andere ebenfalls extraktions-fehlschlagende Zertifikat für
|
||||
denselben Host als vertrauenswürdig durchgehen lassen — ein theoretisches TOFU-Pinning-Bypass-Fenster.
|
||||
|
||||
**Fix:** Rückgabetyp auf `String?` geändert; schlägt die Extraktion fehl, lehnt
|
||||
`RestTransport.urlSession(_:didReceive:completionHandler:)` die Challenge jetzt hart ab
|
||||
(`.cancelAuthenticationChallenge`, kein `lastRejectedFingerprint` gesetzt) — der Nutzer bekommt in
|
||||
diesem Fall nie einen "Zertifikat vertrauen?"-Dialog mit einer nicht verifizierbaren Kennung
|
||||
angeboten, sondern einen normalen Verbindungsfehler.
|
||||
|
||||
Build + alle 101 Unit-Tests grün nach beiden Fixes.
|
||||
|
||||
---
|
||||
|
||||
## Noch nicht geprüft / außerhalb dieses Durchgangs
|
||||
|
||||
- UI-Interaktion selbst (Klickpfade, Darstellung) — nicht automatisierbar, siehe Hinweis oben.
|
||||
|
||||
Reference in New Issue
Block a user