Files
sanctum/THREAT_MODEL.md
T
harald 76c23dbfa3
Sanctum Release / Build & Test (Windows x86_64 & Linux musl) (push) Waiting to run
Sanctum Release / Sign & Release (push) Blocked by required conditions
fix(format-v3): transcript versioning in HMAC and atomic upgrade MAC (F-04, F-05)
2026-09-22 21:02:22 +02:00

163 lines
17 KiB
Markdown

# Threat Model & Sicherheitsarchitektur von Sanctum
Dieses Dokument beschreibt das Bedrohungsmodell, die Sicherheitsannahmen und die Schutzmechanismen von **Sanctum v0.9.5** im reinen Userland-Betrieb.
---
## 1. Sicherheitsziele (Security Objectives)
1. **Vertraulichkeit & Integrität ruhender Daten (Data at Rest)**:
Containerdaten dürfen ohne Kenntnis des Master-Passworts oder des 24-Wort BIP-39 Notfallschlüssels weder entschlüsselt noch unbemerkt manipuliert oder wiederholt werden (Replay Protection).
2. **Reine Userland-Ausführung ohne Kernel-Treiber**:
Vermeidung von Angriffsflächen im Betriebssystem-Kernel (kein Dokan, kein WinFsp, kein unsignierter Treiber). Das gemountete Dateisystem läuft vollständig im Benutzerkontext.
3. **Schutz des Session-Tokens im lokalen Benutzerkontext**:
Das dynamische Session-Token für den lokalen WebDAV-Endpunkt darf weder über Prozesslisten (`argv`), Dateipfade, URL-Query-Parameter noch über Netzwerkinterfaces lecken.
4. **Schutz vor forensischen Spuren (OpSec & Anti-Leak)**:
Verhinderung von Betriebssystem-Artefakten (`Thumbs.db`, `desktop.ini`, ShellBags, NTFS Alternate Data Streams, Swap/Pagefile-Auslagerung).
---
## 2. Bedrohungsmodell & Angreiferprofile
### 2.1 Im Fokus (In Scope)
| Angreifer / Bedrohung | Beschreibung | Sanctum-Gegenmaßnahme |
|---|---|---|
| **Kalter Datenträger-Angriff** | Angreifer hat physischen oder dateibasierten Zugriff auf die `.sanctum`-Datei auf USB-Stick, SSD oder Cloud-Storage. | Argon2id KDF (256 MiB, t=4, p=4), AES-256-GCM mit eindeutiger Chunk-Generation AAD, kanonische HMAC-SHA256 Metadaten-Authentifizierung mit Transkript-Versionierung (Format V3.2, F-01/F-04). |
| **Böswillige Manipulation / Bitrot** | Gezieltes Verändern von Metadaten oder Chunks im Speicher. | AEAD-Tags auf allen Datenblöcken; `sanctum verify` erkennt jede Modifikation; Schreib- und Leseoperationen verwerfen manipulierte Blöcke sofort (`Fail-Closed`). |
| **Replay- & Chunk-Vertauschungsangriffe** | Vertauschen von Chunks zwischen Dateien oder Einspielen alter Versionen. | Kryptografische Bindung aller Chunks an `(node_id, chunk_index, generation)` in den AEAD Additional Authenticated Data (AAD). |
| **Lokale Benutzerisolation** | Mehrbenutzersysteme: Andere Standardbenutzer auf demselben Rechner. | Windows- und Unix-Dateirechte; TCP-Bind ausschließlich an Loopback `127.0.0.1`; dynamisches 128-Bit Session-Token. |
| **DNS-Rebinding & Browser-Angriffe** | Eine im Browser des Nutzers laufende bösartige Website versucht, über DNS-Rebinding auf `http://localhost:<port>` zuzugreifen. | Strikte Fail-Closed Validierung des `Host`-Headers (`127.0.0.1`, `localhost`, `[::1]`). Abweisung aller externen Hostnamen (RT-02). |
| **Argv- & Prozess-Scraping** | Andere Prozesse des gleichen Nutzers oder Monitoring-Tools lesen die Prozess-Kommandozeile aus. | In-Process Netzlaufwerk-Verbindung via `WNetAddConnection2W` (Windows) ohne `net use`-Subprozess. Token wird niemals über `argv` übergeben. |
| **URL- & Proxy-Logging (CWE-598)** | Protokollierung von HTTP-Anfragen in lokalen Logs oder WebDAV-Clients. | Strikte Abweisung von Session-Tokens in URL-Pfad oder Query-String (`403 Forbidden`). Tokens dürfen ausschließlich im `Authorization`- oder `X-Sanctum-Token`-Header übertragen werden (SA-05). |
| **Timing Side-Channel Angriffe** | Messung von Antwortzeiten beim Token-Vergleich. | Strikter Constant-Time Vergleich (`subtle::ConstantTimeEq`) für alle Authentifizierungsprüfungen (SA-06). |
| **RAM-Dump & Pagefile-Forensik** | Windows lagert Arbeitsspeicher in `pagefile.sys` oder `swapfile.sys` aus. | Verriegelung der Schlüssel im physischen RAM via `VirtualLock` (Windows) bzw. `mlock` (Unix) mit RAII-Lebenszeitgarantie (`MemoryLockGuard`, V-03). Sicheres Überschreiben beim Beenden (`zeroize::Zeroizing`). |
| **Slowloris DoS auf Loopback** | Ressourcenerschöpfung durch offengehaltene Sockets. | Beschränkung auf max. 64 gleichzeitige Verbindungen (`MAX_CONCURRENT_DAV_CONNECTIONS`) und 15s Header-Read-Timeout (`HTTP_HEADER_READ_TIMEOUT`). |
| **Begleitdateien-Forensik (-wal/-shm)** | Angreifer analysiert temporäre SQLite-Dateien während oder nach dem Mount. | Sämtliche Daten werden vor Übergabe an SQLite verschlüsselt; WAL/SHM enthalten ausschließlich Ciphertext; TRUNCATE-Checkpointing und Bereinigung beim Aushängen (Z-03). |
| **Nötigung / Schulterblick** | Zwang zur Passwortherausgabe. | Alibi-Carrier (Hidden Vault Modell A) mit steganografisch verstecktem zweiten Tresor und unabhängigen Schlüsseln. |
| **Dateinamen-Swap-Angriffe** | Angreifer vertauscht verschlüsselte Dateinamen zwischen Verzeichnissen. | AAD-Bindung an `parent_id` bei AES-256-GCM Verschlüsselung; Warnung vor `--legacy-names` (deaktiviert diesen Schutz). |
| **Path-Traversal & Gerätenamen** | Angreifer schleust Pfad-Traversal (`..`), reservierte Namen (`CON`, `PRN`) oder Null-Bytes ein. | Strikte Validierung (`validate_node_name`) in allen Schichten (`storage.rs`, `vfs.rs`, `carrier.rs`, `sync.rs`). |
---
### 2.2 Außerhalb des Fokus (Out of Scope / Annahmen)
- **Vollständig kompromittierter Host**: Ein Angreifer mit Kernel-Rootkit, Ring-0-Treiberrechten oder administrativem Keylogger kontrolliert das Gesamtsystem. In diesem Fall kann keine Userland-Anwendung Sicherheit garantieren.
- **Direkte Speicherinjektion unter demselben Benutzerkonto**: Wenn Malware unter demselben Benutzerkonto mit denselben Rechten läuft und `ReadProcessMemory` / `OpenProcess` ausführt, greift das Betriebssystem-Sicherheitsmodell nicht. Sanctum empfiehlt getrennte Benutzerkonten und die Aktivierung von Windows Defender Exploit Protection.
---
## 3. Session-Token Bedrohungsmodell im Detail
### 3.1 Lebenszyklus und Generierung
- Für jede Mount-Sitzung wird ein **frisches 128-Bit kryptografisches Zufallstoken** via `rand::rngs::OsRng` (CryptGenRandom bzw. `getrandom`) generiert.
- Das Token existiert ausschließlich im flüchtigen Speicher des Sanctum-Prozesses und wird nach dem Aushängen sicher aus dem RAM genullt.
### 3.2 Keine Befehlszeilen-Leaks
Unter Windows wird das WebDAV-Netzlaufwerk nicht über einen externen Aufruf wie `net use Z: http://127.0.0.1:8443 /user:...` eingebunden, sondern über den direkten Win32-API-Aufruf:
```c
WNetAddConnection2W(&net_resource, password, username, CONNECT_TEMPORARY)
```
Dadurch tauchen weder das Token noch die Zugangsdaten in der Windows-Prozesstabelle (`Get-Process`, Task-Manager, Sysinternals Process Explorer) auf.
### 3.3 Header-basierte Authentifizierung (SA-05 & SA-06)
- **Erlaubt**:
- `Authorization: Basic <base64(sanctum:token)>`
- `X-Sanctum-Token: <token>`
- **Streng verboten**: Token im URI-Pfad (`http://127.0.0.1:8443/<token>/...`) oder im Query-String (`?token=<token>`). Werden solche Anfragen empfangen, bricht Sanctum die Verarbeitung sofort mit HTTP `403 Forbidden` ab. Dies verhindert, dass Tokens in Referrer-Headern, Browser-Verläufen oder WebDAV-Caches protokolliert werden.
- Alle Vergleiche erfolgen in konstanter Zeit (`ConstantTimeEq`), sodass Angreifer keine Rückschlüsse auf Token-Präfixe über Laufzeitunterschiede ziehen können.
---
## 4. Speicher- und Prozessisolation
1. **VirtualLock & mlock RAII (`MemoryLockGuard`)**:
Der 256-Bit Data Encryption Key (DEK) wird sofort nach der Entschlüsselung im RAM mit `VirtualLock` (Windows) bzw. `mlock` (Linux) verriegelt. Dies garantiert, dass der Schlüssel zu keinem Zeitpunkt vom Windows Memory Manager in die unverschlüsselte Auslagerungsdatei (`pagefile.sys` / `swapfile.sys`) ausgelagert wird.
Durch die Kapselung in `Arc<MemoryLockGuard>` bleibt dieser Schutz auch bei parallelen WebDAV-Anfragen erhalten und wird erst aufgehoben, wenn die letzte Referenz freigegeben wird (V-03).
2. **Zeroizing**:
Alle Schlüsselpuffer (`KEK`, `DEK`, KDF-Zwischenergebnisse) implementieren `zeroize::ZeroizeOnDrop` und werden beim Verlassen des Gültigkeitsbereichs mit Nullen überschrieben.
3. **Session-Lock & Inactivity Shield**:
Sanctum lauscht über `WTSRegisterSessionNotification` auf Sperr-Events (`Win + L`) und Inaktivitäts-Timeouts. Beim Sperren wird das Laufwerk unverzüglich getrennt, alle Caches geleert, WAL-Checkpoints geschrieben und die Schlüssel zerstört.
---
## 5. Dateisystem-Forensik & SQLite WAL/SHM Begleitdateien (Z-03)
### 5.1 Funktionsweise & Ciphertext-Garantie
Während ein Sanctum-Container geöffnet oder aktiv eingebunden ist, nutzt die zugrundeliegende SQLite-Engine den Write-Ahead Logging (WAL) Modus (`PRAGMA journal_mode = WAL`). Dadurch entstehen temporär zwei Begleitdateien im selben Verzeichnis wie der Container:
- `<container>.sanctum-wal` (Write-Ahead Log für Transaktionsdaten)
- `<container>.sanctum-shm` (Shared-Memory-Index für parallele Lese- und Schreibzugriffe)
**Kryptografische Sicherheit**:
Alle Nutzdaten (Chunks) und Inode-Metadaten (Dateinamen) werden **vor** der Übergabe an SQLite im Sanctum-Userland via AES-256-GCM verschlüsselt. Die SQLite-Engine verarbeitet und speichert ausschließlich hochgradig ununterscheidbare Ciphertexte, Nonces, Authentifizierungs-Tags und HMAC-Prüfsummen.
- Zu **keinem Zeitpunkt** gelangen Klartextdaten oder kryptografische Schlüssel (KEK, DEK) in die `-wal`- oder `-shm`-Dateien.
- Selbst bei forensischer Extraktion der `-wal`- und `-shm`-Dateien sieht ein Angreifer ausschließlich unknackbares Zufallsrauschen ohne Entschlüsselungsmöglichkeit.
### 5.2 Sauberes Beenden & Checkpointing
Beim regulären Beenden (`sanctum unmount`, Ctrl+C, Inaktivitäts-Timeout oder Windows-Sitzungssperre) führt Sanctum automatisch:
1. Einen vollständigen WAL-Checkpoint durch (`PRAGMA wal_checkpoint(TRUNCATE)`), der alle ausstehenden Transaktionen in die `.sanctum`-Hauptdatei überführt und die WAL-Datei auf 0 Bytes kürzt.
2. Das Schließen der Datenbankverbindung durch, woraufhin SQLite die `-wal`- und `-shm`-Dateien vom Dateisystem entfernt.
3. Ein explizites Bereinigungs-Fallback aus (`mount.rs`), das verbleibende Begleitdateien sicher vom Host-Dateisystem löscht.
### 5.3 Abrupter Systemabsturz & OpSec-Überlegungen
Wird der Rechner abrupt stromlos gemacht (`Hard Reset`), stürzt das Betriebssystem ab oder wird der Prozess via `SIGKILL` / Task-Manager beendet, verbleiben `<container>.sanctum-wal` und `-shm` möglicherweise auf dem Datenträger.
- **Datenintegrität**: Beim nächsten Öffnen des Containers führt SQLite automatisch ein WAL-Recovery durch, wodurch keine Daten verloren gehen und die Metadaten-Authentifizierung (K-01) intakt bleibt.
- **Forensische Sichtbarkeit**: Ein Angreifer kann aus der Existenz und Dateigröße der `-wal`-Datei ablesen, dass vor dem Absturz Schreiboperationen stattgefunden haben und wie viele Bytes modifiziert wurden.
- **Flash-Wear-Leveling**: Auf SSDs/NVMe-Speichern können gelöschte Dateisystem-Sektoren bis zur TRIM-Bereinigung physisch im Flash-Speicher existieren. Für maximale OpSec empfiehlt Sanctum die Ablage von Containern auf vollverschlüsselten Host-Laufwerken (BitLocker / LUKS) oder RAM-Disks.
---
## 6. Hidden Vault Carrier-Dateisystem & Redundanzmodell (Format V2)
### 6.1 Redundanzhierarchie: Superblock vs. Inode-Pages
Mit Sanctum v0.9.0 führt der Hidden Vault das Carrier-Format V2 (Paged Manifest) ein. Das Redundanzmodell unterscheidet bewusst zwischen Metadaten-Knotenpunkten und Inode-Seiten:
1. **Carrier-Superblock (Vollständige Redundanz auf Block 0 & Block 1)**:
- Der Superblock enthält die essenziellen Dateisystem-Parameter (`root_id`, `next_inode_id`, `free_blocks`, `page_block_indices`) sowie einen monotonen Generationszähler (`manifest_generation`) und CRC32-Prüfsummen.
- Er wird abwechselnd auf Block 0 und Block 1 geschrieben (rollierendes C-02-Schema). Ist einer der beiden Blöcke beschädigt oder unvollständig geschrieben, stellt Sanctum den Superblock transparent aus dem intakten Block wieder her.
2. **Inode-Pages (Dynamisch allokiert, nicht redundant dupliziert)**:
- Inodes werden in 1-MB-Seiten (`CarrierInodePage`, Magic `SANCTPAG`) im normalen Träger-Blockpool gespeichert.
- Zur Maximierung der nutzbaren Speicherkapazität werden Inode-Pages **nicht** blockweise gespiegelt. Stattdessen schützt Sanctum die Konsistenz über Fail-Soft-Isolation (D-01): Fällt eine einzelne Seite durch Bitrot oder Entschlüsselungsfehler aus, wird ausschließlich diese Seite übersprungen. Das restliche Dateisystem bleibt vollständig mountbar und lesbar.
- Erkannte Seitenbeschädigungen werden beim Mounten und in den Systemlogs (`corrupted_pages`) unübersehbar gemeldet.
### 6.2 Pfadauflösungs- und DoS-Schutz (`children_index`, D-02)
- Bei sehr großen Dateisystemen (>10.000 Inodes) führt eine lineare Suche über alle Inodes bei jedem Pfadsegment zu quadratischer Laufzeitkomplexität ($O(N)$ pro Segment).
- Sanctum v0.9.0 hält einen In-Memory-Sekundärindex (`children_index: HashMap<i64, Vec<i64>>`), der Pfadauflösungen auf $O(\text{Geschwister})$ reduziert. Dies verhindert CPU-Erschöpfungs-Angriffe (ReDoS/Algorithmic Complexity Attacks) beim Traversieren tiefer Verzeichnisstrukturen.
### 6.3 Speicherallokationsgrenzen & Transaktionssicherheit (D-03, D-05)
- **Vorabprüfung bei Migration (D-03)**: Bei der transparenten Konvertierung alter V1-Manifeste nach V2 prüft Sanctum vorab, ob ausreichend freie Trägerblöcke vorhanden sind. Reicht der Speicherplatz nicht aus, wird der Speichervorgang ohne Beschädigung des V1-Containers abgebrochen.
- **Kryptografische Blockfreigabe (D-05)**: Werden Inodes gelöscht und Inode-Pages überflüssig, werden die freigegebenen Trägerblöcke sofort mit CSPRNG-Rauschen überschrieben (`shred_carrier_block`), bevor sie an den Freispeicher-Pool zurückgegeben werden.
---
## 7. Dateinamen-Sicherheit und das `--legacy-names`-Flag
### 7.1 AAD-Bindung von Dateinamen
In Sanctum werden Dateinamen mit AES-256-GCM verschlüsselt. Um Swap-Angriffe zu verhindern (bei denen ein Angreifer mit Dateisystem-Zugriff verschlüsselte Dateinamen zwischen Verzeichnissen austauscht), wird die `parent_id` als zusätzliche authentifizierte Daten (AAD) an die Verschlüsselung gebunden.
### 7.2 Sicherheitsrisiko des `--legacy-names`-Flags
Frühere Versionen von Sanctum (vor v0.8.0) verwendeten leere AAD für Dateinamen. Das Flag `--legacy-names` erlaubt die Entschlüsselung von Dateinamen ohne AAD-Bindung als Fallback.
- **Risiko**: Bei aktiviertem `--legacy-names` ist der Schutz vor Vertauschen von Dateinamen aufgehoben. Ein Angreifer könnte Dateien manipulieren, indem er verschlüsselte Namen zwischen verschiedenen Verzeichnissen vertauscht.
- **Empfehlung**: Dieses Flag darf **ausschließlich** zur einmaligen Migration von Altdaten verwendet werden. Im regulären Betrieb muss es deaktiviert bleiben.
---
## 8. Format-V3 Systembindung & Integritätshärtung (F-01 bis F-05)
### 8.1 Transkript-Bindung & Replay-Schutz (F-01, F-04)
- **Problem**: Bei isolierter AEAD-Bindung der Generation im Chunk-Header (`node_id ‖ chunk_index ‖ generation`) konnte ein Angreifer alte Chunk-Zeilen (`ct, nonce, tag, generation`) wiederherstellen, wenn die Datei dieselbe Größe behielt.
- **Kanonischer HMAC**: Sanctum bindet alle sortierten Chunk-Tupel (`ORDER BY node_id, chunk_index: node_id LE64 ‖ chunk_index LE32 ‖ generation LE64`) direkt in das Metadaten-Transkript ein.
- **Transkript-Versionierung (F-04)**: Um ein unbegrenztes Rollback auf v0.9.3-Metadaten-Blobs (`LegacyValid`) zu verhindern, umfasst der HMAC-Transkript-Input die Little-Endian `transcript_ver`:
`b"SANCTUM_META_V3\0" ‖ metadata_gen (LE64) ‖ transcript_ver (LE32) ‖ canonical`.
Sobald ein Container auf `transcript_ver = 2` migriert wurde, lehnt Sanctum ältere 0.9.3-Transkripte strikt als `Invalid` ab.
### 8.2 Autorisierter Header-Rebuild (F-02)
- Ein Rebuild des Metadaten-MACs (`metadata_gen == 0 && metadata_mac IS NULL`) nach einem Header-Restore wird ausschließlich zugelassen, wenn ein kryptografisches CSPRNG-Token (`restore_nonce`) in `meta` existiert und der Benutzer explizit `--rebuild-mac` übergibt oder interaktiv `"JA"` bestätigt. Manipulierte SQLite-Header ohne dieses Token werden unweigerlich abgewiesen.
### 8.3 Transaktions-Atomarität & Resilienz (F-03, F-05)
- Das Format-Upgrade (`upgrade_to_v3`) wird in einer einzigen atomaren SQLite-Transaktion ausgeführt. Bei jeglichem Entschlüsselungs- oder Umschlüsselungsfehler erfolgt ein vollständiger Rollback auf Version 2.
- Der initiale Metadaten-MAC (`transcript_ver = 2`, `gen = 1`) wird vor dem Transaktions-Commit berechnet und geschrieben (F-05), sodass keine ungeschützten Zombie-Container (`version = 3, metadata_mac IS NULL`) entstehen können.
- Im Falle eines abrupten Stromausfalls vor Commit verbleibt der Container sauber auf Version 2. Sollte ein Altsystem dennoch in einen Zombie-Zustand geraten sein, bietet `sanctum upgrade-format` eine automatische Reparatur, sofern kein unautorisierter Restore vorliegt (`restore_nonce IS NULL`).