Skip to content

fix(auth): reject custodial Lightning sign-in when stored signature is empty#3874

Draft
TaprootFreak wants to merge 1 commit into
developfrom
fix/lightning-empty-signature-bypass
Draft

fix(auth): reject custodial Lightning sign-in when stored signature is empty#3874
TaprootFreak wants to merge 1 commit into
developfrom
fix/lightning-empty-signature-bypass

Conversation

@TaprootFreak

Copy link
Copy Markdown
Collaborator

Finding (High, branch-weiter Security-Review)

verifySignature nutzt für custodial Lightning den Vergleichs-Zweig return !dbSignature || signature === dbSignature. Bei Sign-in authentifiziert ein Account mit leerer/null gespeicherter Signatur damit über jede regex-konforme Signatur (/^[a-z0-9]{140,146}$/, trivial erzeugbar) — und doSignIn persistiert danach die Angreifer-Signatur (else if (!user.signature)-Self-Heal) → permanenter Account-Takeover.

Öffentlich erreichbar: /auth/signIn ruft den Service ohne isCustodial auf (Default false), die Regex genügt also. Verifiziert: isCustodial ist nicht angreiferkontrollierbar, aber auch nicht nötig.

Gating: Existenz eines Lightning-Accounts mit leerer gespeicherter Signatur. Der Kommentar // TODO: temporary code to update empty signatures in doSignIn und die nullable Signature-Spalte deuten stark darauf hin, dass solche (Legacy-)Accounts existieren.

Fix

Eine leere gespeicherte Signatur darf niemandem Zugang geben. Ein isSignUp-Flag wird durchgereicht:

  • Sign-up (nichts gespeichert) → erste Signatur wird etabliert (Verhalten unverändert)
  • Sign-in → exakter Match gegen eine nicht-leere gespeicherte Signatur erforderlich

Das richtet Lightning am DeFiChain-Zweig direkt darunter aus, der mit return dbSignature && signature === dbSignature bereits fail-closed ist. Keine Krypto-Verifikation betroffen (EVM etc. laufen unverändert über cryptoService.verifySignature); der legitime Self-Heal für krypto-verifizierte Chains bleibt erhalten.

⚠️ Vor dem Merge zu klären (David / Auth-Owner)

Legacy-Lightning-Accounts mit leerer gespeicherter Signatur können sich nach diesem Fix nicht mehr über den Vergleichs-Pfad einloggen (es gibt kein Credential zum Verifizieren — genau das ist die Lücke). Das ist sicherheitstechnisch korrekt, kann aber legitime Altbestands-User aussperren. Empfehlung: vor dem Merge einen Count solcher Accounts ziehen (Lightning-Adresse + signature IS NULL/''), um den Support-Impact abzuschätzen und ggf. einen Recovery-Pfad (Mail-Login) vorzubereiten. Self-Heal-TODO in doSignIn bei der Gelegenheit mitbewerten.

Tests

Neuer Spec auth-lightning-signature.spec.ts: leere/null gespeicherte Signatur → abgewiesen; falscher Match → abgewiesen; korrekter Match → akzeptiert; Sign-up → etabliert. format:check, type-check, lint sauber; auth-Suite 20/20 grün.

Damit ist der letzte High/Medium-Finding mit Account-Takeover-Potenzial adressiert. Verbleibend: SDK x-kyc-code ohne Origin-Check (packages); Account-Merge Token-Bindung (Auth-Designentscheid).

…s empty

verifySignature returned `!dbSignature || signature === dbSignature` for
the custodial-Lightning comparison branch. On sign-in, an account whose
stored signature is empty/null (legacy accounts — see the 'temporary code
to update empty signatures' self-heal in doSignIn) would authenticate with
ANY signature matching the 140-146 alnum shape, then doSignIn persists the
attacker's signature → permanent account takeover. Reachable via the public
/auth/signIn (isCustodial defaults to false there, the regex is trivially
satisfiable).

A stored empty signature must never authenticate. Thread an isSignUp flag
so sign-up still establishes the first signature (nothing stored yet) while
sign-in requires an exact match against a non-empty stored signature —
aligning Lightning with the DeFiChain branch right below, which already
fails closed on an empty stored signature.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant