syncova-backup/docs/ransomware.md
Jerrit Fritzsche 610719c316
Some checks failed
CI / Backend (Go) (push) Failing after 3m7s
CI / Frontend (React/TypeScript) (push) Successful in 37s
CI / Sicherheitsprüfungen (push) Successful in 44s
Syncova Backups V1
Enterprise-Backup-, Recovery-, Verification-, Security- und
Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme.

Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als
vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit
nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem
tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes
geht in keine Bewertung als "gut" ein.

Umfang (Phasen 0-23):

- Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll,
  Katalogaufbau allein aus den Manifesten — ohne Datenbank
- Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz
  Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck
- Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell)
- Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive
- Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit
- Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center,
  Ransomware-Heuristik (meldet, handelt nie)
- Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing
- Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository
- Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64

Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup
Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs.

Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die
systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine
wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md
und docs/release-candidate.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 09:10:54 +02:00

204 lines
10 KiB
Markdown

# Ransomware-Heuristik (Phase 16)
Die Vorgabe des Implementierungsplans (§18) steht in vier Worten:
> Do not make destructive decisions automatically. Alert first.
Dieses Paket löscht nichts, sperrt nichts und hält nichts an. Es beschreibt, was
auffällig ist, und überlässt jede Entscheidung einem Menschen.
Der Grund ist nicht Vorsicht, sondern Erfahrung: Eine Heuristik, die selbsttätig
handelt, macht aus jedem Fehlalarm einen Schaden — und Fehlalarme wird es geben,
weil ein Betriebssystem-Update von außen genauso aussieht wie ein
Verschlüsselungsangriff. Ein Werkzeug, das bei einem Softwarerollout die
Sicherungskette anhält, wird abgeschaltet. Ein abgeschaltetes Werkzeug erkennt
gar nichts.
## Was gemessen wird
Sechs Signale, alle sechs aus dem Plan. Fünf davon fielen bei der Sicherung
ohnehin an und mussten nur festgehalten werden; eines — der Entropie-Indikator —
verlangte einen Eingriff in die Engine.
| Signal | Herkunft | Untergrenze |
| --- | --- | --- |
| Neu abgelegte Datenmenge | `backups.unique_bytes` | 100 MiB |
| Geänderte Objekte | Zusatzsicherung: `Changes.ChangedFileCount()`; Vollsicherung: alle Dateien | 20 Objekte |
| Verschwundene Objekte | `Changes.DeletedPaths` | 20 Objekte |
| Anteil nicht verkleinerbarer Blöcke | Kompressionsmarker der Engine | 10 Prozentpunkte |
| Neue Dateiendungen | `extension_distribution` (JSONB) | 25 % der Objekte |
| Größe des Laufs | `backups.logical_bytes` | 100 MiB |
**Der Entropie-Indikator kostet nichts, weil die Engine ihn ohnehin bildet.**
Ob ein Block sich komprimieren ließ, entscheidet `ChunkTransformer.Transform`
bei jedem Block. Bislang verschwand diese Erkenntnis im Marker-Byte; jetzt gibt
`Transform` sie zusätzlich zurück. Verschlüsselte Daten sind nicht komprimierbar
— ein Sprung von „5 % der Blöcke unkomprimierbar" auf „100 %" ist das
verlässlichste technische Anzeichen massenhafter Verschlüsselung, das eine
Sicherungssoftware überhaupt sehen kann. Eine eigene Entropiemessung wäre
derselbe Rechenaufwand ein zweites Mal.
**Gezählt werden nur neue Blöcke.** Ein deduplizierter Block wurde in einem
früheren Lauf schon bewertet; ihn erneut mitzuzählen verwässerte den Anteil
genau in dem Lauf, in dem er aussagekräftig wird.
**Die Endungsverteilung ist auf 20 Einträge gedeckelt**, der Rest fällt in einen
Sammelposten `(weitere)`. Ohne Deckel wüchse die JSONB-Spalte mit jeder
Zufallsendung, die eine Schadsoftware erzeugt — ausgerechnet der Angriff bliese
die Datenbank auf. Der Sammelposten ist vom Signal ausgenommen: Er ist per
Konstruktion in jedem Lauf „neu".
## Warum Median und mittlere absolute Abweichung
Der Basiswert entsteht aus den letzten Läufen **derselben Kette**, nicht aus
einer festen Schwelle. Eine feste Schwelle kann es nicht geben: Ein Dateiserver
mit 2 geänderten Dateien je Tag und ein Buildserver mit 40 000 sind beide
normal.
Gerechnet wird mit Median und mittlerer absoluter Abweichung, nicht mit
Mittelwert und Standardabweichung. Der Grund ist der Kern der ganzen Sache:
> Ein einziger Ausreißer ist genau der Fall, den wir erkennen wollen. Würde er
> den Basiswert mitbestimmen, höbe er die Schwelle an, gegen die er gemessen
> wird.
Bei fünf normalen Läufen (~100) und einem Angriff (50 000) läge der Mittelwert
über 8000 — der nächste Angriff derselben Größe fiele nicht mehr auf. Der Median
bleibt bei 100. `TestMedianResistsSingleOutlier` hält das fest.
Weitere Festlegungen:
- **Mindestens fünf Läufe.** Mit dreien ist ein Median eine Formalität und die
Streuung Zufall. Darunter lautet die Einstufung `unknown` — ausdrücklich
getrennt von `none`. Wer nicht messen kann, hat nichts gemessen und darf nicht
so tun, als sei alles in Ordnung.
- **Höchstens zwanzig Läufe.** Ein Basiswert aus einem Jahr beschriebe eine
Anlage, die es so nicht mehr gibt.
- **Nur nach oben geprüft.** Weniger geänderte Dateien als sonst sind kein
Angriffszeichen; eine zweiseitige Prüfung erzeugte an jedem ruhigen Wochenende
einen Befund.
- **Zwei Bedingungen zugleich** — drei mittlere Abweichungen **und** 50 % mehr.
Der Faktor allein schlüge bei sehr gleichmäßigen Werten schon bei
Geringfügigkeiten an; die relative Änderung allein übersähe eine Quelle, die
ohnehin stark schwankt.
- **Streuung null** (eine Quelle, die sich nie ändert) hat keinen Faktor. Dann
zählt allein die relative Änderung.
### Die absolute Untergrenze ist keine Feinheit
Sie kam durch einen Fehlalarm im Test hinzu. Eine Quelle mit zwei geänderten
Dateien je Lauf, jetzt drei: eine Steigerung um fünfzig Prozent, Streuung null —
formal ein Befund, tatsächlich vollkommen belanglos. Deshalb hat jedes Signal
eine eigene Untergrenze. Zwanzig Dateien mehr sind ein Ereignis, zwanzig Bytes
mehr sind Rauschen; eine gemeinsame Grenze für beides gibt es nicht.
Die Erklärung **nennt die Untergrenze**, statt sie zu verschweigen. Ein Satz wie
„der Wert stieg von 336 auf 3 004 350, das liegt unter der Größenordnung" liest
sich bei einem tausendfachen Anstieg wie ein Fehler des Werkzeugs — und wer dem
Werkzeug einmal misstraut, liest auch den echten Befund nicht mehr.
## Einstufung
| Stufe | Bedingung | Schweregrad der Meldung |
| --- | --- | --- |
| `unknown` | weniger als fünf Vergleichsläufe, oder keine Signale erhoben | keine Meldung |
| `none` | kein Signal auffällig | keine Meldung |
| `elevated` | ein Signal auffällig | `warning` |
| `high` | zwei oder mehr Signale auffällig | `high` |
**Zwei, nicht eins**, für die höhere Stufe: Ein einzelnes auffälliges Signal hat
viele harmlose Ursachen — ein großes Update, ein Umzug, ein neuer Datenbestand.
Zwei zugleich sind das Muster, das massenhafte Verschlüsselung hinterlässt:
viele geänderte Dateien **und** kaum noch komprimierbare Daten.
Backups aus der Zeit vor dieser Phase tragen die Kennzahlen nicht. Sie fließen
**nicht** als Nullwerte in den Basiswert ein — das zöge ihn nach unten und ließe
jeden neuen Lauf auffällig erscheinen. Sie werden übersprungen, und solange zu
wenige verwertbare Läufe übrig sind, lautet die Einstufung `unknown`.
## Anbindung
- **Meldungswesen:** Die Regel `unusual_change_rate` nutzt seit dieser Phase den
Detektor statt einer festen Schwelle. Die Meldung nennt die auffälligen
Signale mit Namen und Erklärung.
- **API:** `GET /api/v1/backups/{id}/ransomware-assessment` (`backups.read`)
liefert alle sechs Signale einzeln. Ohne diesen Endpunkt bliebe die Meldung
„4 von 6 Signalen sind auffällig" eine Behauptung: Ihre Empfehlung lautet
„Prüfen Sie die Quelle" — wer aber nicht sehen kann, **welche** vier Signale
gemeint sind, hat keinen Anfang.
- Die Bewertung wird bei jedem Aufruf neu berechnet, nicht gespeichert. Der
Basiswert wandert mit den letzten Läufen; eine eingefrorene Bewertung
beschriebe einen Vergleich, den es so nicht mehr gibt. Dieselbe Entscheidung
wie bei der Recovery Assurance (Phase 10).
Die Empfehlung bei `high` lautet wörtlich:
> Prüfen Sie die Quelle, **bevor** Sie ältere Wiederherstellungspunkte löschen
> oder eine Aufbewahrungsregel anwenden. Die Anlage unternimmt von sich aus
> nichts.
Das ist die einzige Handlung, die die Heuristik überhaupt nahelegt — und sie ist
eine **Unterlassung**. Wer nach einem Verschlüsselungsangriff die Aufbewahrung
laufen lässt, vernichtet die letzten sauberen Wiederherstellungspunkte.
## Nachweis
Geführt gegen den laufenden Dienst, in beide Richtungen. Beide Richtungen sind
nötig: Ein Detektor, der jeden Angriff erkennt, aber auch jeden großen
Arbeitstag meldet, wird nach einer Woche ignoriert.
**Gegentest — harmloser großer Lauf.** 200 neue, gut komprimierbare Dokumente
zu einer Quelle mit sonst drei geänderten Dateien:
```
Einstufung: elevated
Auffällig: 1 von 6 Signalen
⚠ Geaenderte Objekte Bisher lag der Wert stets bei 3.0, jetzt bei 200.0 (6567 Prozent mehr).
```
Richtig: Die Zahl der Dateien stieg sprunghaft — das ist auffällig und wird
gesagt. Der Entropie-Indikator blieb bei 0 %, es verschwand nichts, es kam keine
neue Endung hinzu. Genau **ein** Signal, also `elevated` und ein `warning`, kein
Alarm.
**Angriff — simulierte Verschlüsselung.** 150 Dateien durch Zufallsdaten
ersetzt, mit der Endung `.locked` abgelegt, die Originale gelöscht:
```
Einstufung: HIGH
Auffällig: 4 von 6 Signalen
⚠ Geaenderte Objekte Bisher lag der Wert stets bei 3.0, jetzt bei 150.0 (4900 Prozent mehr).
⚠ Verschwundene Objekte Bisher lag der Wert stets bei 0.0, jetzt bei 150.0 (15000 Prozent mehr).
⚠ Anteil nicht verkleinerbarer Bloecke Bisher lag der Wert stets bei 0.0, jetzt bei 100.0 (10000 Prozent mehr).
⚠ Neue Dateiendungen 1 neue Dateiendungen ([.locked]) betreffen 58 Prozent der Objekte.
```
Der Anteil nicht verkleinerbarer Blöcke sprang von 0 % auf 100 % — das ist der
Fingerabdruck, den nur Verschlüsselung hinterlässt. Beide Meldungen standen
korrekt abgestuft im Meldungswesen (`high` und `warning`), und das Repository
blieb unangetastet: Es wurde nichts gelöscht, nichts gesperrt, nichts angehalten.
## Bekannte Grenzen
- **Die beiden Byte-Signale tragen bei kleinen Quellen nichts bei.** Ihre
Untergrenze liegt bei 100 MiB; im Nachweis oben blieben sie deshalb stumm,
obwohl die Datenmenge um das Achttausendfache stieg. Das ist gewollt — unter
hundert Megabyte ist eine Verschlüsselungswelle weder wirtschaftlich noch
bemerkbar —, bedeutet aber: Bei einer kleinen Quelle stützt sich die Erkennung
auf vier Signale, nicht auf sechs.
- **Ein langsamer Angriff entgeht der Erkennung.** Wer über Wochen täglich ein
Prozent des Bestands verschlüsselt, verschiebt den Basiswert mit sich. Gegen
diesen Fall hilft keine Abweichungsstatistik, sondern die Unveränderlichkeit
aus Phase 11.
- **Die Zahl geänderter Objekte einer Vollsicherung ist die Zahl aller
Dateien.** Ein Wechsel von Zusatz- auf Vollsicherung erzeugt deshalb einen
Ausschlag. Er ist harmlos und wird als `elevated` gemeldet — nicht als `high`,
solange die übrigen Signale ruhig bleiben.
- **Ein Kettenwechsel setzt den Basiswert zurück.** Nach einem neuen Repository
oder einer neuen Quelle lautet die Einstufung fünf Läufe lang `unknown`.
- **Keine Erkennung im laufenden Betrieb.** Bewertet wird ein abgeschlossener
Sicherungslauf. Zwischen Angriff und Meldung liegt bestenfalls ein
Sicherungsintervall. Diese Heuristik ist kein Ersatz für einen Endpunktschutz;
sie ist die letzte Instanz, die den Schaden bemerkt, bevor die Aufbewahrung
die sauberen Wiederherstellungspunkte entfernt.