Authorization disclaimer. This walkthrough applies only to the intentionally vulnerable PortSwigger Web Security Academy lab linked below. Do not attempt these techniques against systems you do not own or have explicit permission to test.
Overview
The lab’s two-step login flow does not securely bind the second-factor check to the account authenticated during the password step. Instead, /login2 uses a client-controlled verify cookie to decide whose code is being checked. Because the code contains four digits and the lab does not rate-limit attempts, changing that cookie to carlos makes it possible to test the complete code space for that synthetic account.

Lab objective/setup
The objective is to access the account belonging to carlos without knowing his password. The provided account wiener is useful for observing the normal authentication sequence: password submission, receipt of a verification code by email, and code submission to POST /login2.
What I observed
After signing in as wiener, the lab delivered a one-time code to the provided email client.

The response from the first login step set verify=wiener in a cookie.

The subsequent /login2 request sent that same cookie alongside the verification code, showing that the second step relied on it to identify the account under verification.

Changing the cookie to verify=carlos caused the application to present the code-entry flow for Carlos rather than rejecting the inconsistent authentication state.


Why it is vulnerable
Authentication state should be maintained server-side and tied to the session that successfully completed the password step. Here, the application trusts a mutable cookie to choose the account for the second factor. The weakness is compounded by a four-digit code and the absence of effective attempt throttling on /login2, leaving only 10,000 possible values.
Walkthrough in the authorized PortSwigger lab
- Complete the normal login flow for
wienerand inspect the requests in Burp Suite. - Send the
POST /login2request to Intruder and change the cookie toverify=carlos. - Mark the four-digit
mfa-codevalue as the payload position and test values from0000through9999within this lab only. - Compare response status and length to identify the response that differs from failed attempts.

In the captured lab session, the distinct response corresponded to code 0293. Using that result opened Carlos’s account.
Verification
The browser displayed Carlos’s account page and the Academy marked the lab as solved. This verifies both parts of the flaw: the altered cookie selected another account, and repeated code attempts were accepted until the correct value was supplied.

Impact and defensive lesson
Bind every MFA challenge to a server-side, short-lived authentication transaction created only after the correct password is supplied. Never use a client-provided username as the authority for selecting the challenged account. Codes should expire promptly, be single-use, and be protected by per-account and per-session attempt limits, progressive delays, monitoring, and safe recovery controls.
References
Migration provenance
This article was rewritten in English from the private migration source declared in the front matter. The reasoning and eight screenshots are preserved; the prose, structure, captions, and accessibility text were normalized without adding observations.