[This lab](https://portswigger.net/web-security/authentication/password-based/lab-broken-bruteforce-protection-ip-block) demonstrates how **brute-force protections** can be rendered ineffective due to a logic flaw in the way the server tracks failed login attempts. Specifically, the server resets your failed login attempt counter when you **log in successfully** — even if you're alternating attempts for different users. By cleverly interleaving valid login attempts for yourself between brute-force attempts on the victim account, you can avoid hitting the failure threshold and **bypass the IP block entirely**. #### Step 1: Investigate Login Behavior 1. Log in at `/login` with incorrect credentials a few times. 2. After **3 failed attempts**, you’ll be blocked (IP-based). ✅ **Observation:** Logging in successfully (e.g., as `wiener`) **resets** the block. --- #### Step 2: Build Interleaved Attack with Burp Intruder 1. Intercept a login POST request in **Burp**: ```http POST /login HTTP/1.1 Content-Type: application/x-www-form-urlencoded username=carlos&password=wrongpass ``` 2. Send it to **Burp Intruder**. 3. Choose **Attack type: Pitchfork** 4. Highlight **both** `username` and `password` fields as payload positions. --- #### Step 3: Setup Payloads (Pitchfork) **Position 1 (username):** Use a list that alternates between your username and the target: ``` wiener carlos wiener carlos ... ``` Ensure your own username appears **before every attempt** on `carlos`. ✅ Repeat pattern for ~100 lines. --- **Position 2 (password):** Alternate your own password (`peter`) with each candidate password: ``` peter password1 peter password2 ... ``` ✅ Each `wiener` attempt uses a correct password to reset the lockout. ✅ Each `carlos` attempt uses a password guess. --- #### Step 4: Configure Throttling 1. Go to **Resource pool** tab. 2. Create a new resource pool with: ``` Max concurrent requests: 1 ``` This ensures **sequential execution**, critical for bypassing timing-based rate limiting. --- #### Step 5: Start the Attack - Launch the Intruder attack - Wait for results to complete --- #### Step 6: Identify the Valid Password - In the results window: - **Filter out** all responses with status `200 OK` - Sort by **username** and look for `carlos` - Look for a response with `302 Found` or a different length/status ✅ This indicates a **successful login**. - Make note of the corresponding **password**. --- #### Step 7: Log in as Carlos - Go to `/login` - Enter: ``` Username: carlos Password: [the successful password] ``` - Visit `/my-account` to solve the lab. --- ##### Why It Works - The server tracks failed logins **per IP**, not per user - A successful login (as `wiener`) **resets** the failed attempt counter for the IP - By interleaving valid logins, you prevent the counter from reaching the block threshold — allowing **unlimited brute-force attempts** on `carlos` --- ##### Real-World Implications - Apps that implement IP-based lockouts **must not allow resets based on other user activity** - This logic flaw is often missed in custom auth workflows or legacy systems - Brute-force protections must be **per user account**, not per IP alone