BUG BOUNTYFIELD MANUAL
Reusable module
Markdown
0 / 6 checkedChecks last until this page reloads.

MFA and passkeys: enrollment, proof, replacement, and recovery

Follow each authenticator from account binding to removal, and validate WebAuthn assertions without mistaking client UI or counter behavior for a security guarantee.

Investigation sequence
  1. 01Record assurance policy
  2. 02Enroll controlled factors
  3. 03Compare fresh and stale proof
  4. 04Check assertion bindings
  5. 05Replace and recover
  6. 06Verify removal

At each step: retain the control → record the observation → continue only while the next boundary is understood.

Used in these playbooks#

Setup and invariant

Reuse identity/session fixtures. Prepare two disposable accounts, recovery access, separate browser profiles, and one reversible protected operation. Record whether the product promises MFA, passwordless login, recent reauthentication, or a particular authenticator class; these are different contracts. The invariant is: a proof must authorize the intended account, ceremony, and assurance level, including factor management. Capture the server's stored factor list and audit events, not just a green browser badge.

Numbered procedure

  1. Test enrollment before authentication. Register A's first and second factors through the legitimate UI. Compare an authenticated registration with anonymous, MFA-pending, and stale-session attempts to complete that same observed operation. For an account-bound enrollment flow, begin in A and attempt completion in B, changing only the account/session context. Confirm the final factor owner with a fresh login. For username-less authentication, successful login to the factor's rightful owner is expected; it must not be reported as cross-account bypass.
  2. Exercise replacement and removal. Capture normal add, rename, delete, recovery-code regeneration, and fallback changes. In the replica, replay one sensitive factor change without the required recent proof, then with a fresh valid proof. Verify whether a newly added factor can log in and whether the removed factor still authenticates. Preserve a recovery route throughout. A factor addition that only changes a label proves nothing. Factor replacement deserves the same care as initial login. OWASP MFA management.
  3. Test OTP and recovery consumption separately. Use A's successful OTP once more in a fresh pending login during its validity window; use an invalid code as the negative control. Test one recovery code, then attempt the consumed code again. Regenerate the recovery-code set and check one old code. Do not brute-force codes or trigger real push/SMS floods. Record which transaction succeeded, not merely whether the numeric value appeared twice. TOTP verification must prevent reuse after successful validation; an identical code displayed during one time step is normal. RFC 6238. Saved recovery credentials also need explicit lifecycle controls. NIST authenticator management.
  4. Build a real passkey baseline. In the local application, open DevTools → More tools → WebAuthn, enable the virtual authenticator, select CTAP2 and the required resident-key/user-verification capabilities, then register through the application's normal page. Record the RP ID and credential owner. This tests server integration; it does not demonstrate compromise of a hardware authenticator. Chrome virtual-authenticator workflow.
  5. Separate signature checks from semantic checks. Compare a fresh assertion with a consumed assertion and one with an invalid signature. For username-first login, verify the credential belongs to the intended account; for discoverable credentials, verify the returned user handle resolves consistently to the credential owner. Trace the verifier's challenge, ceremony type, origin, RP-ID hash, signature, and presence/verification decisions. A local authenticator fixture can sign a deliberately mismatched case; changing signed JSON without re-signing only tests signature rejection. WebAuthn assertion fields.
  6. Check policy-sensitive WebAuthn branches. Verify UV when the ceremony requires user verification; a touch proving user presence does not by itself prove UV. Account for an explicitly configured related-origin deployment and applicable legacy AppID handling before calling an origin/RP mismatch a bypass. Counter anomalies are risk signals, not standalone clone proof; some authenticators keep zero counters. Synced credentials and absent attestation are not automatically weaknesses. Evaluate the deployed library and RP policy against the pinned WebAuthn Level 3 Recommendation.

Local inspection card

Export an owned test assertion in the application's JSON transport format to assertion.json. This prints selected metadata and a challenge fingerprint; it does not verify the signature or establish a vulnerability. If your wrapper uses different keys, adapt the field path.

python3 - <<'PYCODE'
import base64, hashlib, json
from pathlib import Path
x = json.loads(Path('assertion.json').read_text())
s = x['response']['clientDataJSON']
c = json.loads(base64.urlsafe_b64decode(s + '=' * (-len(s) % 4)))
print(json.dumps({
    'type': c.get('type'), 'origin': c.get('origin'),
    'crossOrigin': c.get('crossOrigin'),
    'challenge_sha256': hashlib.sha256(c['challenge'].encode()).hexdigest()
}, indent=2))
PYCODE

Evidence and completion

Report a newly usable unauthorized factor, authentication below a required assurance level, or acceptance of a proof for the wrong account/transaction. Attach the expected rule, before/after factors, request order, independent fresh-login result, and cleanup. Missing notification alone is hardening evidence; a successful server rejection is a passed check.

  • Enrollment and replacement evaluated independently.
  • OTP, backup codes, and passkey ceremonies have separate controls.
  • Username-first and discoverable flows distinguished.
  • Signature rejection separated from signed-context validation.
  • Removed test factors and credentials no longer authenticate.
  • Virtual authenticator exports and live recovery secrets excluded from reports.

Vulnerability reverse references#

Nearby shared procedures#

Object, function, and property authorization · Authentication, recovery, federation, and session lifecycle · Trace input into queries, commands, and templates · Server-side fetching and network trust boundaries · Browser execution, cross-origin reads, and forged actions · Uploads, downloads, paths, archives, and XML · Workflow invariants, replay, idempotency, and races · REST, GraphQL, gRPC, WebSocket, and SSE permission parity