R185-01 (MEDIUM): Die Flanke, die wir selbst gemeldet hatten, hat der
Tester live bestaetigt. seal-backlog war beim ZWEITEN Aufruf genauso
gegatet wie beim ersten ({"confirm":"SEAL"} -> 200), und das Ereignis
landete nur im Audit-Log, nicht im Alarmkanal. Sein Punkt: der
automatische Rueckhalt des Gegenbuchs haengt an `valid` - und `valid`
ueberlebt ein ersetzendes Siegel per Konstruktion. Angriff: Altzeile per
DB-Zugriff loeschen, neu siegeln, Luecke ist beglaubigt, valid wieder
true. Live reproduziert.
Zwei Schichten, in seiner Reihenfolge:
1. Alarmkanal. Neuer SecurityEventType AUDIT_SEAL_CHANGED (Migration
20260826120000). Erstes Siegeln HIGH, Ersetzen CRITICAL - geht damit
ueber sendPendingCriticalAlerts sofort per Mail raus. Die Details
halten Wurzel vorher/nachher und den vollstaendigen Vorbefund fest.
2. Gate. Steht bereits ein Siegel, verlangt der Endpunkt
{"confirm":"RESEAL"} statt SEAL, mit einem Text, der sagt, was dabei
verloren geht. Ein Austausch der Beweisgrundlage soll nicht dasselbe
Wort haben wie das Einrichten.
Und im Gegenbuch selbst: dort stand fuer den Wurzelwechsel ein
console.warn, waehrend der Rueckgabecode auf 0 blieb - also exakt das
Muster, das wir dem CRM zweimal angekreidet haben (R179, R183-02), im
Werkzeug, das dagegen gebaut wurde. Jetzt exit 2, mit alter und neuer
Wurzel samt Blattzahl; "10 Blaetter -> 9 Blaetter" zeigt die Loeschung
sofort. Auch die Erstsiegelung meldet sich, statt stillschweigend
uebernommen zu werden.
Aufloesbar gemacht: der Alarm bricht ab, BEVOR angehaengt wird - ohne
Bestaetigungsweg haette auch ein legitimes Siegeln fuer immer alarmiert
(R183-03-Falle). Neu ist NOTARY_SEAL_ACK, bewusst nicht "true", sondern
die Wurzel selbst (mind. 16 Zeichen): ein stehen gelassener Wert passt
beim naechsten Wechsel nicht mehr und kann keinen weiteren Austausch
durchwinken.
R185-02 (LOW): GET /api/audit-logs?action=<x> gab ungueltige Enum-Werte
roh an die Spalte -> 500. Zweifach schlecht: fehlende Validierung und
Fehler-Orakel (200 vs 500 verraet die Enum-Mitglieder). Jetzt 400 mit
der erlaubten Menge im Klartext. Mitgenommen: sensitivity, Datumsfelder,
Zahlenfelder, Textlaengen und ein Deckel auf limit (200), ueber den sich
sonst die ganze Tabelle an der Seitenlogik vorbei ziehen liess. Beide
Endpunkte.
Getestet ueber HTTP gegen eine Wegwerf-DB, inkl. echtem Gegenbuch-Lauf
mit SSH-signiertem lokalem Repo. Zusaetzlich nachgeholt, was der Tester
nicht herstellen konnte: vollstaendig unsigniertes Protokoll ->
kein_siegel statt der frueheren falschen Entwarnung nicht_noetig, und
seal-backlog nennt den fehlenden Schluessel als naechsten Schritt.
Gegenrichtung geprueft, R183-03 bleibt behoben.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
87 lines
3.6 KiB
Bash
87 lines
3.6 KiB
Bash
# ============================================================
|
||
# Gegenbuch für OpenCRM
|
||
# ============================================================
|
||
# Diese Datei gehört auf den Gegenbuch-Rechner – NICHT auf den CRM-Server.
|
||
#
|
||
# Was hier passiert: Der Rechner holt regelmäßig einen kurzen Kontrollwert von
|
||
# OpenCRM ab und schreibt ihn in ein Buch, das nur hier liegt. Wird später im
|
||
# CRM etwas nachträglich verändert, widerspricht das dem Buch.
|
||
|
||
|
||
# ============================================================
|
||
# Welche Bücher sollen laufen?
|
||
# ============================================================
|
||
# Gültige Werte: prod | staging | prod,staging | (leer = keins)
|
||
# Genau so geschrieben – nicht "production" oder "test".
|
||
#
|
||
# Nur Staging testen: COMPOSE_PROFILES=staging
|
||
# Später Prod dazunehmen: COMPOSE_PROFILES=prod,staging
|
||
# Danach: docker compose up -d (der laufende Dienst bleibt unberührt)
|
||
COMPOSE_PROFILES=staging
|
||
|
||
# Steht in den Einträgen des Buchs. Beliebiger Text, nur Kosmetik.
|
||
NOTAR_EMAIL=gegenbuch@example.de
|
||
|
||
|
||
# ============================================================
|
||
# Produktion
|
||
# ============================================================
|
||
# Adresse der OpenCRM-Instanz, von der geholt wird.
|
||
# Gültig: vollständige URL mit https:// und OHNE Schrägstrich am Ende.
|
||
PROD_CRM_URL=https://crm.example.de
|
||
|
||
# Zugang: ein eigenes Benutzerkonto im CRM, das NUR das Recht "audit:read" hat.
|
||
# Wie man es anlegt, steht in der README unter "Zugang einrichten".
|
||
#
|
||
# Das Gegenbuch meldet sich damit bei jedem Durchlauf selbst an. Ein fest
|
||
# hinterlegtes Token gibt es bewusst nicht – Zugangstoken laufen nach
|
||
# 15 Minuten ab und wären beim nächsten Durchlauf längst ungültig.
|
||
PROD_CRM_EMAIL=gegenbuch@deine-domain.de
|
||
PROD_CRM_PASSWORD=
|
||
|
||
# Wie oft geprüft wird, in Sekunden.
|
||
# Gültig: ganze Zahl > 0. Üblich: 3600 (stündlich), 900 (viertelstündlich)
|
||
# Kürzer heißt: kleineres Zeitfenster, in dem eine Änderung unbemerkt bliebe.
|
||
PROD_INTERVAL=3600
|
||
|
||
# Beim ALLERERSTEN Start einmalig setzen, danach wieder leeren.
|
||
# Gültige Werte: true | (leer)
|
||
# Grund: Die erste Eintragung legt fest, was als Ausgangszustand gilt – das
|
||
# soll nicht versehentlich passieren.
|
||
PROD_GENESIS_ACK=
|
||
|
||
# Normalerweise leer lassen.
|
||
# Gültige Werte: true | (leer)
|
||
# Nur nötig, wenn das Datenverzeichnis verlorenging (z. B. gelöscht) UND du
|
||
# geklärt hast, warum. Siehe README, Abschnitt "Wenn das Gedächtnis fehlt".
|
||
PROD_ADOPT_ACK=
|
||
|
||
# Normalerweise leer lassen.
|
||
# Gültige Werte: die neue Siegelwurzel (mind. 16 Zeichen) | (leer)
|
||
# Das Gegenbuch schlägt Alarm, wenn sich die Wurzel des Bestandssiegels
|
||
# ändert – denn ein erneutes Siegeln ersetzt die Grundlage, gegen die
|
||
# Manipulation nachgewiesen wird. War der Wechsel gewollt, hier die Wurzel
|
||
# eintragen, die der Alarm nennt, einmal laufen lassen und wieder leeren.
|
||
# Bewusst KEIN "true": ein stehen gelassener Wert passt beim nächsten
|
||
# Wechsel nicht mehr und kann darum keinen weiteren stillschweigend
|
||
# durchwinken.
|
||
PROD_SEAL_ACK=
|
||
|
||
# Wo das Buch liegt – relativ zu diesem Verzeichnis.
|
||
# DIESES VERZEICHNIS GEHÖRT INS BACKUP (enthält Buch und Signaturschlüssel).
|
||
PROD_DIR=./data/prod
|
||
|
||
|
||
# ============================================================
|
||
# Test / Staging
|
||
# ============================================================
|
||
# Gleiche Regeln wie oben, eigenes Konto und eigenes Verzeichnis.
|
||
STAGING_CRM_URL=https://staging.example.de
|
||
STAGING_CRM_EMAIL=gegenbuch@deine-domain.de
|
||
STAGING_CRM_PASSWORD=
|
||
STAGING_INTERVAL=3600
|
||
STAGING_GENESIS_ACK=
|
||
STAGING_ADOPT_ACK=
|
||
STAGING_SEAL_ACK=
|
||
STAGING_DIR=./data/staging
|