
Finden Sie die Schwachstelle, die Ihre Tests nie darauf ausgelegt waren zu finden. Ein ReGrade-Demo, das CVE-2023-5968 modelliert: Fangen Sie ein Passwort-Hash-Leck, indem Sie eine App mit sich selbst vergleichen.
Eine praktische Demo zur Zero-Day-Entdeckung mit ReGrade. Sie werden eine gewöhnliche Testsuite auf ReGrade richten, sie gegen einen kleinen Dienst aufzeichnen, sie gegen eine zweite Kopie desselben Dienstes abspielen und mit Claude Code + den ReGrade MCP-Tools einen Passwort-Hash-Leak aufdecken – eine Schwachstelle, für die kein Test geschrieben wurde.
Es modelliert einen echten Fehler: CVE-2023-5968, bei dem der Endpunkt zur Aktualisierung des Benutzernamens einer Kollaborationsplattform das vollständige Benutzerobjekt einschließlich des bcrypt-Passwort-Hashes zurückgab. Er wurde 2017 ausgeliefert und überlebte 7 Jahre Tests, Überprüfungen und Audits. (Curtails Blogbeitrag.)
Der Clou: Es gibt kein v2. Sie vergleichen die App mit sich selbst. Eine frische Instanz hasht ihre Passwörter mit unterschiedlichen bcrypt-Salzen, daher unterscheiden sich die Werte des geleakten Hashes zwischen den beiden Kopien — und diese Entropie ist es, die ReGrade markiert. Die Schwachstelle ist im Code, den Sie bereits ausgeliefert haben, latent vorhanden; es ist keine Versionsänderung erforderlich, um sie zu finden.
regrade-Sensor von https://app.regrade.curtail.com/downloads und setzen Sie REGRADE_API_KEY (oder ~/.regrade/key).claude plugin marketplace add https://app.regrade.curtail.com/downloads/latest/marketplace.json
dann claude plugin install regrade@regrade --scope user und einmal verbinden (/mcp,
angemeldet mit demselben Konto wie Ihr Schlüssel).Eine kleine "Team-Chat"-API (app/store.py) mit Benutzern und Kanälen. Docker Compose startet zwei identische Kopien – gleiches Image, gleicher Code, keine Versionskennung:
http://localhost:8001 – Sie zeichnen dagegen auf.http://localhost:8002 – Sie spielen dagegen ab.Ein Endpunkt hat einen eingepflanzten Fehler:
| Endpoint | Verhalten |
|---|---|
GET /users/<id> | — gibt niemals das Passwort zurück. Die saubere Basislinie. |
Passwörter werden beim Start mit bcrypt gehasht, daher enthalten instance-a und instance-b unterschiedliche Hashes für denselben Benutzer.
git clone https://github.com/Curtail-Inc/hello-ReGrade-security
cd hello-ReGrade-security
docker compose up -d --build
traffic/test_api.py ist eine normale funktionale Testsuite: Anmelden, einen Benutzer lesen, einen Benutzer umbenennen, Kanäle auflisten. Sie testet das CRUD-Verhalten und stellt keine Sicherheitsannahmen – sie prüft nie, ob password durchsickert. (Warum sollte sie? Niemand wusste, dass der Fehler existierte.)
Starten Sie den Sensor-Proxy vor instance-a:
regrade proxy --target http://localhost:8001 --port 19870
Führen Sie in einem anderen Terminal die gleiche Testsuite aus – setzen Sie einfach BASE_URL auf den Proxy. Dies ist die einzige Änderung:
BASE_URL=http://localhost:19870 python -m pytest traffic/test_api.py
Alle Tests bestehen, unverändert. Stoppen Sie den Proxy (Strg-C); die Aufzeichnung wird hochgeladen und gibt eine Recording ID: <uuid> aus – notieren Sie diese.
regrade replay --rec-id <RECORDING_ID> --target http://localhost:8002
Auf beiden Seiten derselbe Code – die einzigen Unterschiede sind die Werte, die eine frische Instanz generiert.
Öffnen Sie dieses Repository in Claude Code und bitten Sie es, Sie durch das Replay zu führen. Geleitet von der CLAUDE.md dieses Repositorys wird es:
summarize_deltas ausführen → mehrere Deltas: das Login-token, die created_at-Zeitstempel der Kanäle und — leise darunter — $.password.create_id_mapping für das Session-$.token (eine dynamische ID, kein Rauschen zum Verwerfen),create_filter_rule DROP für $.channels[*].created_at (ein pro-Start-Zeitstempel),apply_profile_to_replay, dann query_deltas(unlabeled_only=true) – wiederholen, bis nur noch ein Delta übrig ist.$.password – ein bcrypt-Hash in einem Antworttext. Ein Leak der CVE-Klasse, gefunden ohne Vorkenntnisse und ohne Sicherheitsannahmen.Sowohl das Session-Token als auch der Passwort-Hash unterscheiden sich zwischen den beiden Läufen – beide sind hochgradig entropische Zeichenketten, die sich jedes Mal ändern. Das eine ist legitimes Rauschen, das Sie mappen; das andere ist ein Bruch. Sie können sie nicht anhand von „es hat sich geändert" unterscheiden – Sie müssen darauf schauen, was sich geändert hat. Wenn Sie jedes hochgradig entropische Feld als Rauschen wegfiltern würden, hätten Sie die Schwachstelle versteckt.
Das ist die Lektion: ReGrade validiert keine Erwartungen, es vergleicht Verhalten – so kann es die Fehler aufdecken, für die niemand einen Test zu schreiben gedachte.
app/store.py ist eine Datei. Die GET-Pfade rufen sanitize() auf; der PATCH-Pfad vergisst es. Schauen Sie nachdem Sie es mit ReGrade gefunden haben – der Punkt ist, dass ReGrade es allein aus Traffic aufgespürt hat, indem es die App mit sich selbst verglichen hat.
Apache-2.0.
PATCH /users/<id> (rename) | Der Fehler — gibt das vollständige Benutzerobjekt einschließlich des bcrypt-password-Hashes zurück. Ein fehlender sanitize()-Aufruf, genau wie in CVE-2023-5968. |