Files
opencrm/tools/audit-notary/.env.example
T
duffyduckandClaude Opus 5 e81a83ae8f Siegelwechsel ist ein Alarm, kein Hinweis (Pentest R185-01/-02)
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>
2026-08-26 09:41:11 +02:00

87 lines
3.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================
# 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