On this page
2FA Broken Logic
Lab
2FA broken logic · Apprentice
Solution
Given
This lab's two-factor authentication is vulnerable due to its flawed logic. To solve the lab, access Carlos's account page.
Your credentials: wiener:peter
Victim's username: carlos
You also have access to the email server to receive your 2FA verification code.
Analyzing the task
There is broken 2FA logic on the site, we have our own account where we can look at how the mechanism works. To solve the lab, we need to access user carlos's page.
Recon
Let's go through the 2FA flow as our own user.
POST /login, with username and password in the body. Response + redirect to/login2:Set-Cookie: verify=wiener; HttpOnly Set-Cookie: session=EBdAlyofdB1mRMdQSvTDuKzeWSgj9t64; Secure; HttpOnly; SameSite=None- On
GET /login2there's a 2FA code input form. We enter it from email.POST /login2, with codemfa-code=1507in the body, and the cookie is sent:Cookie: session=EBdAlyofdB1mRMdQSvTDuKzeWSgj9t64; verify=wiener
The response is 302 — successful login.
Interestingly, the verify cookie is set at the first step, then at the second step there's a redirect to the code input page. Essentially this cookie tells the server which user the request is for, and we can swap it. Let's try calling GET /login2 with verify=carlos and thereby trigger generation of a 2FA code for him. Then, using a call to POST /login2, try to perform a brute-force attack on the code — its length is only 4 characters.
- We send a code-generation request
GET /login2forcarlosby settingverify=carlos. - We get the code input form, click submit code.
- A
POST /login2request flies out — we drop it into Intruder. - We choose the "Brute forcer" payload, set 4 characters.
- We add a variable to the request body:
mfa-code=§pwd§. - We launch the attack.
We look for the 302 redirect. We got the code — 0314. We send the request:
POST /login2
Cookie: session=MAEXN9XadoWSU7iCsN4RFiE6GEQnk1hs; verify=carlos
mfa-code=0314
The response is 302 with a new cookie. We take the session cookie, swap it in our browser, refresh the page.
Lab solved!
More in this category
Web Shell Upload via Extension Blacklist Bypass (PortSwigger Lab)
.php is blacklisted, but .htaccess uploads without complaint — we slip our own Apache config in and make the server execute shell.bug as PHP.
Web Shell Upload via Obfuscated File Extension (PortSwigger Lab)
Extension blacklist rejects .php and a double-extension shell.php.jpg is served as an image — a null byte in shell.php%00.jpg bypasses both checks.
Remote Code Execution via Web Shell Upload (PortSwigger Lab)
Avatar upload has no validation — drop a PHP web shell and read /home/carlos/secret.