Multifactor authentication and its limits
Multifactor authentication (MFA) is the single most effective step an ordinary user can take to protect an account. It is not magic, though. Testers regularly find MFA implementations whose design flaws let an attacker walk around the second factor. Understanding these limits makes you a better tester, and a better defender.
Scope reminder
Bypassing authentication on a system you are not authorised to test is a serious offence, covered in France by articles 323-1 to 323-3-1 of the Penal Code. The ideas here are explained at a conceptual level and are meant to be checked on your own lab or in an authorised audit. Do not try to defeat the MFA of real accounts, including your own accounts on third-party services.
The idea: something you know, have, are
Authentication factors fall into three families:
- Knowledge: something you know, such as a password or PIN.
- Possession: something you have, such as a phone, a hardware security key or a code generator.
- Inherence: something you are, such as a fingerprint or face.
MFA combines at least two different families. A password plus a security question is not MFA, since both are knowledge. The benefit is that stealing one factor is not enough: a leaked password alone no longer opens the account.
Common second factors, from weaker to stronger
| Method | Strengths | Weaknesses |
|---|---|---|
| SMS or voice code | Easy for everyone | Phone number takeover, interception, phishing |
| Email code | No extra device | Only as safe as the mailbox |
| Authenticator app (time-based one-time passwords) | Works offline, no number takeover | Codes can still be phished in real time |
| Push notification approval | Convenient | “Fatigue” attacks, where users approve out of annoyance |
| Security keys and passkeys (FIDO2/WebAuthn) | Bound to the real site, resistant to phishing | Setup and recovery planning needed |
Any MFA is much better than none. The table simply explains why guidance from agencies such as ANSSI and NIST encourages phishing-resistant methods for sensitive accounts.
How time-based codes work
An authenticator app and the server share a secret, set during enrolment (often by scanning a QR code). Every 30 seconds, both compute a short code from that secret and the current time. The server accepts the code if it matches, usually allowing a small time window for clock differences. Nothing is sent between phone and server except the code you type, so it works offline.
Where MFA implementations fail
Most real problems come from the way the second step is wired into the application, not from cryptography. Test each of these ideas in your lab, in a training application or Academy lab that includes an MFA step.
1. The second step can be skipped
Think of a bouncer who checks your password at the first door, then trusts that you will walk to the second door for the code check. If the application marks the user as “logged in” after the password step and simply relies on the front end to display the code page, a user might go directly to a page that requires authentication and be let in. Test: after entering the password but before entering the code, try navigating directly to a protected page. A secure application treats the session as partially authenticated until the second factor is validated, and refuses access to protected pages.
2. No limit on code attempts
A six-digit code has a million possibilities, which is tiny for a computer if nothing limits attempts. The application must restrict the number of tries per account and invalidate the code after a few failures, and codes must expire quickly. Test in the lab: how many wrong codes does the application accept before reacting?
3. Code reuse or long validity
A one-time code should work once. Verify whether a code can be reused, or whether older codes remain valid.
4. Logic trusting client-side values
Some flaws come from trusting data sent by the browser: a parameter such as “mfa_verified” in a request, a cookie that records the state, or a response that the client-side script interprets (“success: true”). If the server trusts what the client says about the second factor, it is not really verifying anything. In Burp, check whether the verification outcome is decided on the server and not visible or alterable in the request.
5. A weaker path around MFA
Recovery routes are a classic bypass. Does “Forgot password” log the user in without asking for the second factor? Do backup codes have the same protection as normal codes? Does the mobile application or an old API endpoint skip MFA entirely? The account is only as strong as its weakest entry route, as we saw in the previous lesson.
6. Enrolment and removal without re-authentication
Turning off MFA or adding a new device should require the user to prove their identity again. Otherwise, a briefly hijacked session becomes a permanent compromise.
7. Real-time phishing and fatigue
Beyond application bugs, attackers can ask victims to enter their codes on a look-alike site and relay them instantly, or bombard them with push requests until one is approved. These are attacks on people and protocols, not on code. They are the reason why phishing-resistant factors (security keys, passkeys) are recommended for important accounts, and why number matching and rate limits are used on push prompts.
Designing MFA well: the defender’s list
- Treat the session as incomplete until every factor is verified, server side.
- Limit attempts, add delays, and expire codes quickly; make codes single-use.
- Apply MFA consistently to all paths: web, mobile, API, recovery.
- Require re-authentication to change security settings.
- Offer phishing-resistant options and provide secure recovery options such as printed backup codes kept safe.
- Notify users when a new device is enrolled or MFA is turned off.
Tip
As a user, enable MFA on your email account first. Email is the gateway to every password reset, so a compromised mailbox puts all your other accounts at risk. Cybermalveillance.gouv.fr gives simple instructions for enabling it.
Testing mindset: logic over tools
Notice how the MFA flaws above rarely need sophisticated tools. They need questions: what state does the server remember between the two steps? What happens if I skip, repeat or reorder steps? This reasoning about workflow carries into chapter 5 on business logic, where order, state and trust are central.
Your turn: draw and test the MFA flow
For an application or Academy lab that includes a second factor, draw the flow on paper: each request, what the server remembers, what is checked. Then write five test cases, from the list above, that you would run on it in an authorised lab. For each, say what a secure application would do.
See a solution
A sample plan, in table form:
| Test | Secure behaviour |
|---|---|
| Skip the code page and request a protected page | Access refused, redirect back to the code step |
| Submit many wrong codes in a row | Delay, lockout or a new login required |
| Reuse a code already accepted | Refused |
| Use the recovery flow without the second factor | Second factor or equivalent proof still required |
| Disable MFA from an active session | Password or second factor requested again |
Your flow diagram should show a state such as “password verified, MFA pending” between the two steps. If you cannot find that state in the application, that is a clue for the first test.
Key takeaways
- MFA combines factors from different families and greatly reduces the value of a stolen password.
- SMS and email are better than nothing; security keys and passkeys resist phishing best.
- Most failures are flaws in logic: a skippable step, no attempt limit, reusable codes, client-trusted values or a weaker recovery path.
- The session must remain partially authenticated until all factors are verified on the server.
- Changing security settings must require fresh proof of identity.
You have now covered the front door. In chapter 3 we move inside the application and look at what happens when user input is treated as instructions: injection.