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

10 KiB

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.