Bestandssiegel: Altbestand gegen stille Aenderung gesichert (Pentest R171-02)
Bei Hash-Version 1 sind nur 7 von 24 Spalten gehasht. Ein DB-Schreibzugriff konnte eine LOGIN_FAILED-Zeile auf success=1 setzen, das Label umschreiben und errorMessage leeren - alles Nicht-Hash-Felder, Hash unveraendert - und /verify meldete weiterhin valid=true. Ein Einbruchsversuch war unsichtbar in einen Erfolg umschreibbar. Rueckwirkend signieren geht nicht, ein Rehash waere die falsche Medizin. Stattdessen ein einmaliges, nicht destruktives Bestandssiegel: je Altzeile ein Blattwert, die Wurzel darueber in einem HMAC-signierten Marker. Umgesetzt nach den vier Bedingungen aus dem Pentest: 1. Blaetter ueber den vollen Zeileninhalt inkl. id und hashVersion, nicht ueber den 7-Feld-V1-Hash - sonst lebte die Luecke im Siegel weiter. 2. Wurzel signiert (steht im Marker, der selbst V3/HMAC ist). Ohne AUDIT_HMAC_KEY wird das Siegeln abgelehnt. 3. Bereich fix auf [1 ... v3FromId-1] statt Live-Abfrage hashVersion < 3. Sonst haette ein Up-Flip der Grenzzeile sie aus der geprueften Menge gedraengt. 4. Pruefung je id: vorhanden, weiterhin Altbestand, Inhalt == Blatt, dazu Wurzelabgleich. Neuer Endpunkt POST /audit-logs/seal-backlog (audit:admin, confirm SEAL). /verify meldet den Siegelzustand im Klartext, auch wenn kein Siegel existiert. Verifiziert in separater Wegwerf-DB mit Mischbestand (6xV1, 5xV2, 5xV3): ohne Siegel ist der Angriff unsichtbar, mit Siegel wird er erkannt und die Zeile benannt; der Up-Flip der Grenzzeile wird ebenfalls erkannt. Wegwerf-DB danach geloescht, Dev-Daten unberuehrt. tsc + vite build gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1274,6 +1274,23 @@ model RefreshTokenRecord {
|
||||
@@index([customerId])
|
||||
}
|
||||
|
||||
/// Blattwerte des Bestandssiegels (Pentest R171-02 / R172).
|
||||
///
|
||||
/// Der Altbestand (Hash-Version 1/2) laesst sich nicht rueckwirkend signieren –
|
||||
/// ein Siegel vergibt man beim Anlegen. Bei V1 sind nur 7 von 24 Spalten
|
||||
/// gehasht, ein DB-Schreiber kann dort z. B. `success` von false auf true
|
||||
/// setzen, ohne den Hash zu beruehren: die Pruefung meldet weiterhin "gueltig".
|
||||
///
|
||||
/// Das Bestandssiegel schliesst das, ohne irgendetwas umzuschreiben: Zum
|
||||
/// Zeitpunkt X wird je Altzeile ein Blattwert ueber den VOLLEN Inhalt
|
||||
/// (alle Spalten inkl. id und hashVersion) gebildet; die Wurzel darueber
|
||||
/// steht in einem HMAC-signierten Marker. Jede spaetere Aenderung an einer
|
||||
/// Altzeile bricht Blatt und Wurzel.
|
||||
model AuditBacklogSeal {
|
||||
auditLogId Int @id
|
||||
leafHash String
|
||||
}
|
||||
|
||||
enum AuditAction {
|
||||
CREATE
|
||||
READ
|
||||
|
||||
Reference in New Issue
Block a user