# Hashverkettete Audit-Logs: Was sie beweisen und was nicht

Eine Hash-Kette kann starke Belege dafür liefern, dass eine Gruppe von Audit-Datensätzen nach ihrer Erstellung nicht bearbeitet, neu angeordnet oder unbemerkt in der Mitte ergänzt wurde. Sie beweist nicht, dass die Anwendung jedes relevante Ereignis protokolliert hat, dass ein Zeitstempel der tatsächlichen Zeit entspricht oder dass ein bestimmter Mensch eine Aktion ausgeführt hat. Wer sie als Beweis für all das behandelt, baut beeindruckend aussehende Nachweise, die bei der ersten ernsthaften Nachfrage zusammenbrechen.

Ich habe erlebt, dass Untersuchungen ins Stocken geraten, weil Menschen von einem Log Antworten auf Fragen erwarteten, für die es nie ausgelegt war. Eine Kette ließ sich problemlos prüfen, trotzdem konnte niemand feststellen, ob der Dienst die abgewiesene Anfrage protokolliert hatte, ob die Identität des Operators echt war oder ob die Systemuhr abgewichen war. Die Kryptografie war in Ordnung. Das Nachweispaket war unvollständig.

Für Entwickler, die Agents mit Zugriff auf APIs und SSH betreiben, ist diese Unterscheidung besonders wichtig. Ein Agent kann viele Aktionen schnell ausführen. Später ist die entscheidende Frage oft sehr konkret: Welcher Prozess hat diesen Aufruf angefordert, unter welcher Berechtigung, welche genaue Anfrage hat der Executor gesendet, was kam zurück und hat jemand die Aktion genehmigt? Eine Hash-Kette schützt einen Teil dieser Geschichte. Den Rest musst du selbst erfassen.

## Eine gültige Kette beweist Kontinuität der Datensätze, nicht die Realität

Eine gültige Hash-Kette beweist, dass jeder vorhandene Datensatz den vorherigen Datensatz bindet und dass die Reihenfolge seit dem gewählten Startpunkt intern konsistent geblieben ist. Ändert jemand ein altes Ereignis, vertauscht zwei Ereignisse oder fügt einen Datensatz zwischen zwei bestehende ein, schlägt die Prüfung fehl, sofern diese Person nicht alle späteren Verknüpfungen neu berechnen und jeden vertrauenswürdigen Prüfpunkt ersetzen kann.

Das ist ein aussagekräftiger Nachweis. Ein Ermittler kann sagen: «Diese Datensätze bilden dieselbe Reihenfolge, aus der dieser bekannte Kettenkopf hervorgegangen ist.» Die Formulierung ist wichtig. Die Aussage setzt einen bekannten Kettenkopf oder eine andere vertrauenswürdige Referenz voraus. Liegen die einzige Kopie der Kette und ihr abschließender Digest auf derselben Maschine, die ein Angreifer kontrolliert, kann er beides umschreiben.

Eine Hash-Kette beweist nicht:

- dass die Anwendung jedes Ereignis beobachtet hat, das hätte aufgezeichnet werden sollen,
- dass die Ereignisdaten korrekt beschreiben, was außerhalb des Loggers passiert ist,
- dass die Ereigniszeit einer zuverlässigen Uhr entspricht,
- dass ein Mensch und nicht ein kompromittierter Prozess mit dessen Zugangsdaten die Aktion ausgelöst hat,
- dass die Kette begann, bevor ein Angreifer die Kontrolle über das System erlangte.

Das sind unterschiedliche Aussagen mit unterschiedlichen Nachweisen. Nenne ein Log nicht «manipulationssicher». Software erhält diesen Status nicht, nur weil sie SHA-256 verwendet. Eine Kette macht Änderungen unter bestimmten Annahmen erkennbar. Das ist die nützliche und vertretbare Eigenschaft.

Die Unterscheidung zwischen **Integrität** und **Vollständigkeit** verdient besondere Aufmerksamkeit. Bei der Integrität geht es darum, ob vorhandene Datensätze verändert wurden. Bei der Vollständigkeit geht es darum, ob Datensätze fehlen. Eine Kette beantwortet die erste Frage gut. Die zweite beantwortet sie nur, wenn externe Nachweise sowohl die erwarteten Prüfpunkte als auch den Ereignisumfang festlegen, den der Logger ausgeben musste.

## Das Format des Datensatzes entscheidet, was der Hash tatsächlich abdeckt

Eine Kette schützt nur die Bytes, die in den Digest eingehen. Lege vor der Diskussion über Algorithmen ein kanonisches Ereignisformat fest und nimm alle Felder auf, die ein Ermittler zur Interpretation der Aktion braucht.

Ein minimaler Datensatz kann so aussehen:

```json
{
  "sequence": 1842,
  "event_id": "7b2ea6de-9c3f-4bb4-b1d7-8b13fbb1c5b9",
  "recorded_at": "2025-03-08T17:14:22.481Z",
  "actor": {"kind": "agent_process", "process_id": "p-91f"},
  "action": "http.request",
  "target": "api.example.internal/v1/releases",
  "request_digest": "sha256:...",
  "result": {"status": 201, "response_digest": "sha256:..."},
  "previous_hash": "sha256:..."
}
```

Der Schreiber serialisiert den Datensatz in einer festgelegten Form, hasht diese Bytes und speichert den resultierenden Digest als Verweis auf den Vorgänger im nächsten Datensatz. Konzeptuell:

```text
record_hash[n] = SHA-256(canonical_record[n])
canonical_record[n+1].previous_hash = record_hash[n]
```

Das Feld `previous_hash` muss selbst in den Bytes liegen, die `record_hash[n]` abdeckt. Es wegzulassen ist ein peinlicher, aber realer Implementierungsfehler. In diesem Design tragen die Datensätze Digest-ähnliche Verzierungen, ohne die Reihenfolge zu binden.

Kanonisierung ist kein Detail. Zwei JSON-Serialisierer können Objektfelder unterschiedlich anordnen, Unicode unterschiedlich maskieren oder Zahlen unterschiedlich formatieren. Ein Prüfer, der JSON neu erstellt, statt die exakt gespeicherten Bytes zu prüfen, kann ehrliche Datensätze ablehnen oder, schlimmer noch, unterschiedliche Auffassungen darüber erzeugen, was der Datensatz bedeutet. Speichere die ursprüngliche Byte-Darstellung, lege die Kodierung fest und teste die Prüfung mit unabhängigen Implementierungen.

Die Kette sollte den Kontext abdecken, nicht nur den Anfragetext. Ein Datensatz mit der Aussage «bereitgestellt» ist ein dünner Nachweis. Ein Datensatz, der die Version des Executors, den Aktionstyp, die Zielkennung, die authentifizierte Prozessidentität, die Autorisierungsentscheidung, den Anfrage-Digest, den Antwort-Digest, die Sequenznummer und die Aufzeichnungszeit bindet, gibt einem Prüfer etwas, das er bewerten kann. Er beweist weiterhin nicht, dass jedes Feld wahr ist, verhindert aber, dass ein späterer Bearbeiter die Geschichte Feld für Feld verändert.

Die NIST Special Publication 800-92, *Guide to Computer Security Log Management*, bringt denselben praktischen Punkt in einfacheren betrieblichen Begriffen auf den Punkt: Log-Datensätze brauchen genügend Angaben zu Ereignis, Quelle, Benutzer, Status und Zeit, um eine Analyse zu ermöglichen, und Organisationen müssen ihre Log-Daten schützen. Eine perfekte Kette um vage Datensätze bewahrt vage Datensätze perfekt. Das ist kein Audit-Design.

## Der erste Datensatz und das fehlende Ende bleiben ungeschützt

Jede Kette hat einen ersten Datensatz, oft Genesis-Datensatz genannt. Sein Vorgängerwert wird per Konvention festgelegt, etwa als Digest einer leeren Bytefolge, oder er verweist auf einen früheren Prüfpunkt. Danach kann die Kette Kontinuität herstellen. Sie kann nicht erklären, warum dieser Punkt der Beginn der Geschichte ist.

Nehmen wir einen Dienst, der die Datensätze 1 bis 10.000 lokal speichert. Ein Angreifer erlangt vollständige Kontrolle, löscht die Datensätze 1 bis 7.000, ändert das Sequenzfeld der verbleibenden Datensätze und erstellt eine neue Kette ab dem früheren Datensatz 7.001. Die gefälschte Kette lässt sich prüfen. Ein Prüfer ohne früheren Prüfpunkt sieht keinen kryptografischen Fehler.

Dasselbe Problem besteht am Ende. Ein Absturz, Stromausfall oder Angreifer kann verhindern, dass die letzten Ereignisse dauerhaft gespeichert werden. Der letzte erhaltene Datensatz kann korrekt geprüft werden, obwohl wenige Augenblicke später eine Aktion stattfand. Die Kette beweist, dass das gespeicherte Ende nachträglich nicht verändert wurde. Sie beweist nicht, dass es das tatsächlich letzte Ereignis ist.

Beide Lücken lassen sich verringern, indem du Prüfpunkte außerhalb der Kontrolle des Schreibers ausstellst. Ein Prüfpunkt enthält mindestens die Kettenkennung, die Sequenznummer, den Datensatz-Hash und die Prüfpunktzeit. Sende ihn an ein separates Konto, einen nur einmal beschreibbaren Speicher, einen externen Zeitstempeldienst oder einen unabhängig verwalteten Collector. Ein signierter Prüfpunkt ist besser als ein unsignierter, weil er die Aussage an eine Signaturidentität bindet.

RFC 3161 beschreibt ein Zeitstempelprotokoll, bei dem eine Zeitstempelstelle den Nachweis signiert, dass sie einen Nachrichtenabdruck zu einer bestimmten Zeit gesehen hat. Das kann eine enge und nützliche Aussage stützen: Die Stelle hatte diesen Digest zu diesem Zeitpunkt. Es sagt nicht, ob die Ereignisdaten ehrlich waren, ob frühere Ereignisse vor dem eingereichten Prüfpunkt ausgelassen wurden oder ob der Akteur berechtigt war. Nutze es für Nachweise von Zeit und Existenz, nicht als Ersatz für betriebliche Aufzeichnungen.

Die Häufigkeit von Prüfpunkten ist eine Risikoentscheidung. Häufige Prüfpunkte verkleinern das Zeitfenster, in dem jemand ein noch nicht verankertes Ende entfernen kann. Sie erzeugen aber auch mehr externe Datensätze, die aufbewahrt und abgeglichen werden müssen. Tu nicht so, als würden stündliche Prüfpunkte eine minutengenaue Rekonstruktion von Vorfällen schützen. Halte das maximale nicht verankerte Zeitfenster in deiner Betriebsanweisung fest.

## Ein Hash macht aus einem Zeitstempel keine vertrauenswürdige Zeit

Ein Log-Zeitstempel gibt an, was die Uhr des Loggers beim Erstellen des Datensatzes angezeigt hat. Für gewöhnliches Debugging kann das ausreichen. Bei Fragen zu Fristen, Handelsfenstern, Zugriffen nach einer Kündigung oder der Reihenfolge von Ereignissen auf verschiedenen Maschinen ist es ein schwacher Nachweis.

Ein Administrator kann eine lokale Uhr verstellen. Eine virtuelle Maschine kann mit einer veralteten Zeit fortgesetzt werden. Die Netzzeitsynchronisierung kann ausfallen. Selbst ein korrekt synchronisierter Host zeichnet auf, wann seine Anwendung das Ereignis geschrieben hat. Das kann sich davon unterscheiden, wann ein entfernter Dienst die Anfrage empfangen oder die Änderung gespeichert hat.

Halte diese Zeiten getrennt, wenn der Unterschied wichtig ist:

- `observed_at`: wann die Ursprungskomponente das Ereignis beobachtet hat,
- `recorded_at`: wann der Audit-Schreiber seinen Datensatz erstellt hat,
- `remote_at`: eine vom entfernten System zurückgegebene Zeit, sofern es eine liefert,
- `checkpoint_at`: wann ein unabhängiger Zeuge einen Kettenkopf akzeptiert hat.

Fasse sie nicht in einem harmlosen Feld `timestamp` zusammen. Jede Zeit stammt aus einer anderen Quelle und hat ein anderes Fehlverhalten. So kann ein Ermittler mit einem Zeitbereich arbeiten, statt sich auf falsche Genauigkeit zu verlassen.

Wenn du einen Zeitnachweis brauchst, dokumentiere, wie der Host seine Zeit synchronisiert, bewahre Warnungen über den Zustand der Synchronisierung auf und sichere signierte Quittungen für Prüfpunkte. Bei Vorgängen mit großen Konsequenzen solltest du den lokalen Datensatz mit dem eigenen Audit-Eintrag des entfernten Dienstes vergleichen. Eine Anfrage, die um 10:02:01 protokolliert wurde, und eine entfernte Änderung um 10:02:05 können dieselbe Aktion beschreiben. Die Kette schützt deinen Datensatz vor Bearbeitung. Der Abgleich verbindet ihn mit dem externen System.

Eine häufige Empfehlung lautet: «Verwende eine nur erweiterbare Datenbank und Zeitstempel, dann ist das Audit-Problem gelöst.» Sie ist beliebt, weil sie betrieblich einfach klingt. Sie ist falsch, weil das Anhängen innerhalb eines Dienstes wenig über das Vertrauen in die Uhr, fehlende Ereignisse, Identität oder externe Auswirkungen aussagt. Nutze einen nur erweiterbaren Speicher, wenn er passt, aber benenne, welcher Nachweis weiterhin fehlt.

## Zuordnung erfordert eine Identitätsspur außerhalb des Digests

Eine Hash-Kette kann eine Zuordnungsangabe wie `actor = alice@example.com` bewahren. Sie kann nicht beweisen, dass Alice die Zugangsdaten eingegeben hat, dass der Identitätsanbieter sie korrekt authentifiziert hat oder dass ein Angreifer ihre aktive Sitzung nicht verwendet hat. Der Digest schützt den Satz, nicht seine Wahrheit.

Bei Agent-Aktionen ist die Prozessidentität oft hilfreicher als ein vages Benutzerfeld. Erfasse die Kennung des Agent-Prozesses, soweit vorhanden den übergeordneten Prozess, die Signaturstelle der ausführbaren Datei, die Startzeit, die Sitzungskennung und das Benutzer- oder Dienstkonto, das die Sitzung autorisiert hat. Ein Prozessname allein ist ein schwacher Nachweis. Jedes Programm kann einen vertrauten Namen wählen.

Code-Signaturen ermöglichen eine begrenzte Aussage: Das Betriebssystem kann feststellen, dass eine ausführbare Datei eine Signatur trägt, die einer Signaturstelle zugeordnet ist, und dass die Signatur nach den Regeln der Plattform gültig ist. Das beweist nicht, dass der Betreiber der ausführbaren Datei gute Absichten hatte. Es hilft aber, einen bekannten Build von einer beliebigen Binärdatei mit demselben Dateinamen zu unterscheiden.

Auch Authentifizierung und Autorisierung brauchen getrennte Datensätze. Authentifizierung sagt, welche Zugangsdaten oder welcher Principal vom System akzeptiert wurde. Autorisierung sagt, warum das System diese Aktion zu diesem Zeitpunkt erlaubt hat. Ein Bestätigungsdialog, eine Rollenzuweisung, ein Token-Bereich oder ein Änderungs-Ticket kann als Autorisierungsnachweis dienen. Nimm eine stabile Referenz oder einen Digest dieser Entscheidung in den Aktionsdatensatz auf und bewahre den zugrunde liegenden Entscheidungsdatensatz mit Zugriffskontrollen auf.

Digitale Signaturen verbessern diese Ebene, wenn sie richtig eingesetzt werden. Signiert ein Audit-Schreiber regelmäßig Kettenköpfe, kann ein Prüfer kontrollieren, dass der Inhaber eines privaten Schlüssels diese Signaturen erzeugt hat. Das fügt gegenüber einem unverschlüsselten Hash eine Aussage über die Quelle hinzu. Es hängt weiterhin von der Verwahrung des privaten Schlüssels, dem Zertifikatsstatus, den Rotationsaufzeichnungen und der Zuordnung zwischen Zertifikatsinhaber und realer betrieblicher Identität ab.

Verstecke all das nicht in einer einzigen Zeichenkette `user`. Während eines Vorfalls müssen Menschen unterscheiden können zwischen dem Menschen, der einen Lauf genehmigt hat, dem Prozess, der die Aktion angefordert hat, dem Dienst, der sie ausgeführt hat, und der Stelle, die die Zugangsdaten akzeptiert hat. Das können vier verschiedene Akteure sein.

## Autorisierungsnachweise beantworten eine andere Frage als Aktivitätsdaten

Ein Aktivitätsdatensatz beantwortet die Frage: «Was hat der Executor getan?» Ein Autorisierungsdatensatz beantwortet: «Warum durfte er das tun?» Teams führen beides oft zusammen, weil es bei derselben Anfrage auftaucht. Das macht Untersuchungen schwieriger.

Nehmen wir an, ein Agent fordert einen SSH-Befehl an. Der Executor zeichnet Zielhost, Befehls-Digest, Ergebnis, Prozessidentität und Zeit auf. Separat hält die Autorisierungsschicht fest, dass ein neuer Prozess eine Genehmigung erhalten hat, wer ihn genehmigt hat, worauf sich die Genehmigung bezog und wann sie ablief. Führt der SSH-Befehl später aus, sollte das Aktivitätsereignis auf den geltenden Autorisierungsdatensatz verweisen.

So kann ein Prüfer die richtigen Fragen stellen. Wurde der Befehl ausgegeben? Prüfe den Aktivitätsdatensatz. Hatte die Sitzung die erforderliche Berechtigung? Prüfe den Autorisierungsdatensatz. Zeigte der Bestätigungsbildschirm eine korrekte Identität? Prüfe die Aufzeichnungen der Benutzeroberfläche und der Prozessidentität. Hat der entfernte Host den Befehl ausgeführt? Prüfe seine Server-Logs oder das daraus entstandene Ergebnis.

Eine Genehmigung für eine Sitzung und eine Genehmigung für jede sensible Nutzung von Zugangsdaten liefern unterschiedliche Nachweise. Eine Sitzungsfreigabe belegt, dass eine Person einem bestimmten Prozess erlaubt hat, während seiner Laufzeit zu arbeiten. Eine Genehmigung pro Aktion belegt eine engere Entscheidung nahe an einem konkreten Vorgang. Keine Variante ist automatisch besser. Die Wahl hängt von Häufigkeit, Folgen und der Frage ab, ob ein Mensch wiederholte Aufforderungen realistisch bewerten kann.

Genehmigungsmüdigkeit ist ein Designfehler und kein Grund, Genehmigungen nicht mehr aufzuzeichnen. Sieht eine Person Hunderte nicht unterscheidbare Anfragen, liefern die daraus entstehenden Klicks kaum Nachweise für eine überlegte Autorisierung. Bündle risikoarme Arbeit unter einer begrenzten Sitzungsentscheidung, verlange wiederholte Bestätigungen für Zugangsdaten oder Aktionen, deren Ziel und Folgen der Mensch beurteilen kann, und beschreibe den Umfang in klaren Worten.

Auch ein Genehmigungsereignis kann für sich genommen keine informierte Zustimmung beweisen. Es beweist, dass der Genehmigungsmechanismus eine Entscheidung aufgezeichnet hat. Welche Prozessdetails dem Benutzer angezeigt wurden, wie diese Anzeige an den ausführenden Prozess gebunden war und wie der Audit-Datensatz aussah, entscheidet darüber, welches Gewicht die Entscheidung später hat.

## Vollständigkeit hängt davon ab, wo Aktionen den Logger umgehen können

Du erhältst kein vollständiges Protokoll von Agent-Aktionen, indem du einer Log-Datei nachträglich eine Hash-Kette hinzufügst, wenn der Agent bereits über die ursprünglichen Zugangsdaten verfügt. Sobald ein Agent ein API-Token oder einen privaten SSH-Schlüssel erhält, kann er einen anderen Client aufrufen, das Geheimnis kopieren oder eine Anfrage außerhalb deines geprüften Pfads stellen. Die Kette kann die von ihr gesehenen Anfragen zuverlässig bewahren und trotzdem genau die wichtigen übersehen.

Vollständigkeit beginnt mit der Kontrolle der Aktionsgrenze. Die Komponente, die die Zugangsdaten besitzt, sollte die Netzwerk- oder SSH-Aktion selbst ausführen und Entscheidung sowie Ergebnis protokollieren, bevor sie ein Ergebnis zurückgibt. Der Agent sollte das Ergebnis erhalten, nicht das Geheimnis. Dadurch verändert sich die Aussage von «Wir haben den Agent gebeten, seine Arbeit zu protokollieren» zu «Der Besitzer der Zugangsdaten hat jede Nutzung über diesen Kanal beobachtet».

Auch dann muss der Umfang ausdrücklich festgelegt werden. Wenn ein Entwickler dieselben Zugangsdaten zusätzlich in einem Terminal verwenden kann, deckt der Audit-Trail die vom Agent vermittelten Nutzungen ab, aber nicht jede Nutzung dieser Zugangsdaten. Wenn ein Agent einen zweiten Netzwerkpfad erreichen kann, der den Executor umgeht, deckt der Trail diesen Pfad nicht ab. Eine Aussage über Vollständigkeit muss den abgedeckten Kanal, Principal und Zeitraum nennen.

Sallyport folgt dieser Grenze bei seinen unterstützten HTTP- und SSH-Kanälen: Der verschlüsselte Tresor hält API- und SSH-Zugangsdaten vom Agent fern, während die App die Aktion ausführt und aufzeichnet. Dadurch hat der Audit-Trail einen größeren Umfang als ein Aktivitäts-Log auf Agent-Seite. Er macht jedoch keine Aussagen über Aktionen, die über einen unabhängigen Zugangsdatenpfad ausgeführt werden.

Ein nützlicher Fehlertest besteht darin, jeden Weg von einem Agent zu einer externen Wirkung aufzuzeichnen. Beziehe direkte HTTP-Clients, Shell-Tools, lokale Dateien mit Tokens, Browsersitzungen, Cloud-Metadaten-Dienste, CI-Variablen und SSH-Konfigurationen ein. Jeder Weg außerhalb des protokollierten Executors ist eine Ausnahme von jeder Vollständigkeitsbehauptung. Schließe ihn, isoliere ihn oder benenne die Ausnahme ehrlich.

## Vertraulichkeit, Zugriff und Aufbewahrung brauchen eigene Kontrollen

Hash-Ketten geben für sich genommen nichts preis. Audit-Datensätze enthalten jedoch oft Informationen, die du nicht in ein gewöhnliches Anwendungs-Log schreiben würdest. Anfrage-URLs können Kundenkennungen offenlegen. Befehlszeilen können Geheimnisse enthalten. Antworten können personenbezogene Daten enthalten. Eine Kette, die diese Datensätze schwer veränderbar macht, kann auch eine unbedachte Offenlegung schwer rückgängig machen.

Verschlüssele den Audit-Speicher und beschränke, wer ihn lesen darf. Trenne nach Möglichkeit die Fähigkeit zur Integritätsprüfung von der Fähigkeit, Inhalte zu entschlüsseln. Ein Prüfer kann Hashes über verschlüsselten Datensatz-Bytes neu berechnen und die Vorgängerreferenzen vergleichen, ohne die geschützten Inhalte zu sehen. Das ist nützlich, wenn ein Prüfer zunächst feststellen muss, dass ein versiegeltes Archiv intakt ist, bevor ein berechtigter Ermittler es öffnet.

Maskierung muss erfolgen, bevor der Datensatz in die Kette gelangt. Ein nachträgliches Ersetzen eines Geheimnisses verändert die Bytes und beschädigt die Kette. Erfasse stattdessen einen Digest des vertraulichen Anfrageinhalts, eine stabile Token-Referenz, gegebenenfalls die Länge oder eine strukturierte Angabe, dass ein Feld zurückgehalten wurde. Dokumentiere die Maskierungsregel. Sonst können zwei ähnlich aussehende Datensätze mit unterschiedlichen Regeln maskiert worden sein.

Auch die Aufbewahrung beeinflusst den Beweiswert. Wenn ein Aufbewahrungsprozess alte Datensätze löscht, sollte er einen eigenen Datensatz erzeugen, der den gelöschten Bereich, die maßgebliche Aufbewahrungsregel, den Löschzeitpunkt und den letzten Prüfpunkt vor der Löschung nennt. Bewahre den Prüfpunkt in einem separaten Archiv auf. Eine Kette kann gelöschtes Material nicht zurückbringen. Die verbleibenden Nachweise können jedoch zeigen, dass die Löschung nach einem festgelegten Verfahren und nicht heimlich erfolgte.

Auch Zugriffe müssen protokolliert werden. Erfasse, wer ein Audit-Archiv exportiert, wer es entschlüsselt und wer die Aufbewahrungskonfiguration ändert. Audit-Logs ziehen während eines Vorfalls Aufmerksamkeit auf sich. Die Kette schützt frühere Datensätze vor unbemerkten Änderungen. Eine große Gruppe von Lesern kann vertrauliche Inhalte jedoch weiterhin kopieren oder einen Operator dazu bringen, zukünftige Protokollierung zu unterdrücken.

## Prüfe das Archiv, bevor du es brauchst

Die Prüfung sollte ein routinemäßiger Vorgang mit gespeichertem Ergebnis sein, kein Befehl, den jemand während eines Ausfalls zum ersten Mal ausprobiert. Deine Vorgehensweise sollte den genauen Archivbereich, die Version des Prüfers, die erwartete Quelle des Prüfpunkts, den Prüfzeitpunkt, den Operator und das Ergebnis festlegen.

Ein Prüfer muss mindestens vier Fehler erkennen: fehlerhafte Datensätze, eine falsche Vorgängerreferenz, einen Datensatz, dessen Digest nicht zu den gespeicherten Bytes passt, und eine Abweichung zwischen dem berechneten Kettenkopf und einem erwarteten Prüfpunkt. Die Ausgabe sollte sich leicht aufbewahren lassen. Zum Beispiel:

```text
$ audit verify --archive agent-actions-2025-03-08.log --checkpoint checkpoints/2025-03-08.json
chain_id: agent-actions-prod-a
records_checked: 1842
first_sequence: 1
last_sequence: 1842
computed_head: sha256:4e7c...a912
checkpoint_head: sha256:4e7c...a912
result: VALID
```

`VALID` bedeutet, dass der Prüfer die bereitgestellten Bytes mit dem bereitgestellten Prüfpunkt verglichen hat. Es bedeutet nicht «Jede Aktion in der Produktion ist vorhanden» oder «Die Ereignisse sind wahr». Schreibe diese Einschränkung direkt in die Vorgehensweise. Menschen, die unter Druck ein grünes Ergebnis sehen, werden ihm sonst mehr Bedeutung beimessen, als es verdient.

Teste zerstörerische Fälle in einem nicht produktiven Archiv. Ändere ein Byte im Datensatzkörper. Verschiebe zwei Datensätze. Lösche einen Datensatz in der Mitte. Ersetze den Kettenkopf des Prüfpunkts. Kürze das Ende. Der Prüfer sollte jeden Fall ablehnen, mit Ausnahme einer gewöhnlichen Kürzung des Endes ohne erwarteten abschließenden Prüfpunkt. In diesem Fall kann er ein gültiges Präfix melden. Das Ergebnis ist korrekt und sollte dich aus dem richtigen Grund beunruhigen.

Sallyport bietet eine Offline-Prüfung der Kette über `sp audit verify`. Der Prüfer kann die verschlüsselte Audit-Kette ohne Tresorschlüssel prüfen. Führe diese Prüfung nach Exporten aus und übe den Abgleich mit den getrennten Sitzungs- und Aktivitätsansichten, bevor eine Untersuchung dich dazu zwingt.

## Ein Nachweispaket braucht Datensätze, die produktiv voneinander abweichen

Eine belastbare Untersuchung verwendet mehrere Datensätze mit unterschiedlichen Fehlermodi. Die Übereinstimmung unabhängiger Quellen wiegt mehr als ein einzelnes Log, das seine eigenen Annahmen wiederholt.

Bewahre für eine sensible Agent-Aktion den hashverketteten Aktivitätsdatensatz, den Sitzungs- oder Genehmigungsdatensatz, die authentifizierte Prozessidentität, die relevante Konfigurationsversion, die externe Prüfpunktquittung und den eigenen Datensatz oder das beobachtbare Ergebnis des Zielsystems auf. Für gewöhnliche Anfragen brauchst du nicht jede Quelle. Du brauchst genug Quellen, gemessen an den Folgen eines Irrtums.

Rechne damit, dass Quellen gelegentlich voneinander abweichen. Der lokale Aktivitätsdatensatz kann dem Zeitstempel des entfernten Dienstes vorausgehen, weil die Netzwerkübertragung Zeit benötigt hat. Eine Anfrage kann eine erfolgreiche Antwort liefern, während das entfernte System den Vorgang später zurückrollt. Ein Sitzungsdatensatz kann eine Genehmigung zeigen, während der Aktionsdatensatz keine Nutzung der erteilten Berechtigung ausweist. Solche Unterschiede sind Untersuchungsnachweise und keine Fehler, die man glätten sollte.

Schreibe die genauen Aussagen auf, die dein System stützen kann. Zum Beispiel: «Dieses Archiv enthält eine unveränderte Folge von Executor-Datensätzen bis zum Prüfpunkt X.» Schreibe anschließend die Aussagen auf, die es ohne weitere Datensätze nicht stützen kann: «Dieses Archiv allein beweist nicht, dass keine direkte Nutzung der Zugangsdaten stattgefunden hat.» Klare Grenzen machen starke Aussagen glaubwürdig.

Die erste praktische Maßnahme besteht darin, eine Agent-Operation mit großen Konsequenzen von Anfang bis Ende zu rekonstruieren. Bestimme die Aktionsgrenze, die vor der Ausführung geschriebenen Felder, die danach geschriebenen Felder, die Genehmigungsnachweise, das Ziel des Prüfpunkts, die Bestätigung durch das entfernte System und jeden Umgehungspfad. Wenn irgendein Teil davon davon abhängt, dass sich jemand an das Geschehen erinnert, hast du noch keinen Audit-Trail. Du hast eine Geschichte, die den Kontakt mit einem Vorfall möglicherweise nicht übersteht.
