Prerequisites
- Target system, dependencies and environment configured.
Usage
Purpose
MFA is the single most effective control against credential theft — but only if the factor resists the attack you face and the enforcement can't be skipped. A poorly implemented second factor (SMS, or a check the client can bypass) gives false confidence. This skill covers choosing factors, adding step-up for sensitive actions, and testing that the enforcement actually holds.
When to use it
Designing authentication for any app that matters, hardening after a credential-stuffing scare, or reviewing an existing MFA implementation for bypasses. Pairs with the authentication-testing and session-management skills.
Choosing factors (weakest to strongest)
- SMS / email OTP — better than nothing, but phishable and vulnerable to SIM-swap. Avoid for high-value accounts; acceptable as a fallback only.
- TOTP (authenticator app) — a shared-secret 6-digit code. Phishable (a fake site relays it in real time) but not SIM-swappable. A reasonable default.
- Push notification — convenient, but vulnerable to MFA fatigue (bombing the user with prompts until they approve). Needs number-matching to be safe.
- Phishing-resistant: FIDO2 / WebAuthn / passkeys — the strong choice. The credential is bound to the origin, so a phishing site can't relay it. Use these for privileged accounts and, ideally, everyone.
Procedure (reviewing/testing)
- Confirm MFA is actually enforced server-side. The classic bypass: the app checks the password, sets a session, and treats MFA as a second page the client can skip. Try navigating straight to a post-login endpoint after the password step — if it works, MFA is cosmetic.
- Test the OTP flow for weaknesses: is the code rate-limited (or can you brute-force a 6-digit code)? Does it expire? Is it single-use? Can you reuse a code, or request unlimited new ones?
- Test MFA fatigue resistance on push: does approving require number-matching, or can an attacker spam prompts until the user taps approve?
- Test step-up for sensitive actions (change email/password, high-value transfer) — are these gated behind a fresh factor, or does a normal session suffice? A session hijacked or a CSRF shouldn't be able to perform them without re-auth.
- Test recovery/backup flows — account recovery that bypasses MFA (email a reset that skips the second factor) undermines the whole control. This is a favourite bypass.
- Check remember-this-device doesn't weaken things (long-lived, transferable trust tokens).
Cheatsheet
factor strength: SMS < TOTP < push(w/ number-match) < FIDO2/WebAuthn/passkey
bypass tests
[ ] skip the MFA step -> reach post-login endpoint directly? (cosmetic MFA)
[ ] OTP: brute-forceable? reusable? no expiry? unlimited re-requests?
[ ] push: MFA fatigue -> spam prompts, no number-matching?
[ ] sensitive action performed WITHOUT step-up re-auth?
[ ] account recovery path SKIPS MFA? (the classic backdoor)
[ ] remember-device token long-lived / portable?
step-up = require a fresh factor at the moment of a sensitive action,
not just at login.
Reading the output
- Reaching a logged-in state without completing MFA = enforcement bypass; the second factor is theater. Critical — MFA that can be skipped protects no one.
- A brute-forceable OTP (no rate limit on a 6-digit code) = the factor is defeatable in thousands of tries; a real weakness.
- Push with no number-matching = MFA fatigue works; users get bombed into approving. Enforce number-matching.
- A recovery flow that skips MFA = the whole control has a back door; often the easiest bypass and frequently missed.
- Sensitive actions with no step-up = a stolen session or CSRF can do the damage MFA was meant to prevent.
The fix
- Enforce MFA server-side as part of establishing the authenticated session — the session isn't fully authenticated until the second factor is verified. No client-skippable step.
- Prefer phishing-resistant factors (FIDO2/WebAuthn/passkeys), especially for admins; they defeat real-time phishing that TOTP and SMS don't.
- Harden OTP: rate-limit attempts, short expiry, single-use, and limit re-requests.
- Number-matching on push to kill MFA fatigue, and alert on repeated denied prompts.
- Step-up for sensitive actions — require a fresh factor at the moment of the action, not just at login.
- Secure the recovery path to the same bar as login — recovery must not be an MFA bypass.
Pitfalls
- Client-side MFA enforcement. If the second factor is a page the client can skip, it's not enforced. Bind it to the session server-side.
- SMS for high-value accounts. SIM-swap and phishing make it weak; reserve it as a last-resort fallback.
- Ignoring recovery flows. The strongest MFA is undone by a reset email that skips it.
- Push without number-matching. Fatigue attacks work; users approve to make the prompts stop.
- Login-only MFA. Without step-up, a hijacked session performs sensitive actions freely.
References
- OWASP Multifactor Authentication Cheat Sheet
- NIST SP 800-63B (authenticator assurance levels)
- FIDO Alliance / WebAuthn documentation
- CWE-287, CWE-308 (single-factor where multi-factor required)
Inputs
- Relevant source code, logs, network traces, or system specifications.
Outputs
- Analysis findings, security audit report, or generated code artifacts.
1---2name: mfa-and-step-up3description: Use when adding or reviewing multi-factor and step-up authentication — choosing factors that resist real attacks and enforcing them so they can't be bypassed.4---5678## Prerequisites9- Target system, dependencies and environment configured.1011## Usage12### Purpose1314MFA is the single most effective control against credential theft — but only if the factor resists the attack you face and the enforcement can't be skipped. A poorly implemented second factor (SMS, or a check the client can bypass) gives false confidence. This skill covers choosing factors, adding step-up for sensitive actions, and testing that the enforcement actually holds.1516### When to use it1718Designing authentication for any app that matters, hardening after a credential-stuffing scare, or reviewing an existing MFA implementation for bypasses. Pairs with the authentication-testing and session-management skills.1920### Choosing factors (weakest to strongest)2122- **SMS / email OTP** — better than nothing, but phishable and vulnerable to SIM-swap. Avoid for high-value accounts; acceptable as a fallback only.23- **TOTP (authenticator app)** — a shared-secret 6-digit code. Phishable (a fake site relays it in real time) but not SIM-swappable. A reasonable default.24- **Push notification** — convenient, but vulnerable to **MFA fatigue** (bombing the user with prompts until they approve). Needs number-matching to be safe.25- **Phishing-resistant: FIDO2 / WebAuthn / passkeys** — the strong choice. The credential is bound to the origin, so a phishing site can't relay it. Use these for privileged accounts and, ideally, everyone.2627### Procedure (reviewing/testing)28291. **Confirm MFA is actually enforced server-side.** The classic bypass: the app checks the password, sets a session, and treats MFA as a second page the client can skip. Try navigating straight to a post-login endpoint after the password step — if it works, MFA is cosmetic.302. **Test the OTP flow for weaknesses**: is the code rate-limited (or can you brute-force a 6-digit code)? Does it expire? Is it single-use? Can you reuse a code, or request unlimited new ones?313. **Test MFA fatigue resistance** on push: does approving require number-matching, or can an attacker spam prompts until the user taps approve?324. **Test step-up** for sensitive actions (change email/password, high-value transfer) — are these gated behind a fresh factor, or does a normal session suffice? A session hijacked or a CSRF shouldn't be able to perform them without re-auth.335. **Test recovery/backup flows** — account recovery that bypasses MFA (email a reset that skips the second factor) undermines the whole control. This is a favourite bypass.346. **Check remember-this-device** doesn't weaken things (long-lived, transferable trust tokens).3536### Cheatsheet3738```39factor strength: SMS < TOTP < push(w/ number-match) < FIDO2/WebAuthn/passkey4041bypass tests42 [ ] skip the MFA step -> reach post-login endpoint directly? (cosmetic MFA)43 [ ] OTP: brute-forceable? reusable? no expiry? unlimited re-requests?44 [ ] push: MFA fatigue -> spam prompts, no number-matching?45 [ ] sensitive action performed WITHOUT step-up re-auth?46 [ ] account recovery path SKIPS MFA? (the classic backdoor)47 [ ] remember-device token long-lived / portable?4849step-up = require a fresh factor at the moment of a sensitive action,50 not just at login.51```5253### Reading the output5455- **Reaching a logged-in state without completing MFA** = enforcement bypass; the second factor is theater. Critical — MFA that can be skipped protects no one.56- **A brute-forceable OTP** (no rate limit on a 6-digit code) = the factor is defeatable in thousands of tries; a real weakness.57- **Push with no number-matching** = MFA fatigue works; users get bombed into approving. Enforce number-matching.58- **A recovery flow that skips MFA** = the whole control has a back door; often the easiest bypass and frequently missed.59- **Sensitive actions with no step-up** = a stolen session or CSRF can do the damage MFA was meant to prevent.6061### The fix6263- **Enforce MFA server-side** as part of establishing the authenticated session — the session isn't fully authenticated until the second factor is verified. No client-skippable step.64- **Prefer phishing-resistant factors** (FIDO2/WebAuthn/passkeys), especially for admins; they defeat real-time phishing that TOTP and SMS don't.65- **Harden OTP**: rate-limit attempts, short expiry, single-use, and limit re-requests.66- **Number-matching on push** to kill MFA fatigue, and alert on repeated denied prompts.67- **Step-up for sensitive actions** — require a fresh factor at the moment of the action, not just at login.68- **Secure the recovery path** to the same bar as login — recovery must not be an MFA bypass.6970### Pitfalls7172- **Client-side MFA enforcement.** If the second factor is a page the client can skip, it's not enforced. Bind it to the session server-side.73- **SMS for high-value accounts.** SIM-swap and phishing make it weak; reserve it as a last-resort fallback.74- **Ignoring recovery flows.** The strongest MFA is undone by a reset email that skips it.75- **Push without number-matching.** Fatigue attacks work; users approve to make the prompts stop.76- **Login-only MFA.** Without step-up, a hijacked session performs sensitive actions freely.7778### References7980- OWASP Multifactor Authentication Cheat Sheet81- NIST SP 800-63B (authenticator assurance levels)82- FIDO Alliance / WebAuthn documentation83- CWE-287, CWE-308 (single-factor where multi-factor required)8485## Inputs86- Relevant source code, logs, network traces, or system specifications.8788## Outputs89- Analysis findings, security audit report, or generated code artifacts.