2FA bypass using a brute force attack

3 min read Easy PortSwigger
Authentication
Contents

On this page

The lab

here is how portswigger describes it

This lab's two-factor authentication is vulnerable to brute-forcing. You have already obtained a valid username and password, but do not have access to the user's 2FA verification code. To solve the lab, brute-force the 2FA code and access Carlos's account page.

Victim's credentials: carlos:montoya

the broken logic 2FA lab let us slip past the second factor through a flaw in which account the code belonged to. this one has no such shortcut. we already own carlos's password, so the only thing between us and his account is a four digit code, and four digits is a small enough space to simply guess all of it. the real obstacle is that the app keeps logging us out mid attack.

why this needs session handling, not just intruder#

a four digit code has only ten thousand possible values, which is nothing for a tool like intruder. normally you would point it at the code field and let it run. the complication here is a defence that logs you out after two wrong codes, which kills your session long before you have worked through ten thousand guesses.

so each guess needs a fresh, valid logged in session to be submitted against. doing that by hand is impossible, but burp can automate it with session handling rules and a macro. a macro is just a saved sequence of requests burp can replay, so we record the full login as carlos and tell burp to run that macro before every single request intruder sends. that way each code guess arrives on a newly logged in session, the two wrong tries logout never gets a chance to bite, and intruder can grind through the whole range uninterrupted.

Step 1 - record the login as a macro#

we log in as carlos and look at the 2FA step, confirming that two wrong codes drops us back to logged out. to keep ourselves logged in, we build a session handling rule.

in burp settings under sessions we add a new session handling rule. on its scope tab we set the url scope to include all urls so the rule applies to our attack traffic. then under select macro we add a macro and record the three requests that make up a full login:

GET /login
POST /login
GET /login2

we test the macro and check that its final response is the page asking for the four digit security code. that confirms the macro logs carlos all the way back in and lands on the 2FA prompt, ready for a code. we click through the dialogs to save it.

Step 2 - brute force the code with the macro refreshing the session#

we send the POST /login2 request to intruder and put a payload position on the mfa-code parameter.

for the payloads we choose the numbers type over the range 0 to 9999 with a step of 1, and set both the minimum and maximum integer digits to 4 so values like 7 are sent as 0007. that produces every possible four digit code. with the session handling rule in place, burp silently replays our login macro before each of these guesses, so every attempt is made on a live session rather than a dead one.

Step 3 - force single ordering and solve#

there is one ordering requirement. the macro logs in and then the guess is submitted, and that pairing has to stay in step, so we cannot have requests firing in parallel and racing each other. we open the resource pool panel and set maximum concurrent requests to one, which makes intruder send strictly one guess at a time with its login refresh neatly in front of it.

we start the attack and let it work through the range. almost every response is a rejected code, but eventually one request returns a 302 redirect, which means that code was accepted and carlos is being logged in. we right click that request, show the response in the browser, and load the url it points at to follow the redirect into carlos's session and his account page.

with this, the lab is solved!