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>
204 lines
10 KiB
Markdown
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.
|