[This lab](https://portswigger.net/web-security/authentication/password-based/lab-username-enumeration-via-response-timing) demonstrates a real-world authentication weakness involving **response timing differences**. The login mechanism leaks information about whether a username is valid based on **how long the server takes to respond**. Additionally, the app includes **IP-based rate limiting**, which can be bypassed using the `X-Forwarded-For` header. The attack combines three techniques: 1. **Timing-based enumeration** 2. **Brute-force protection bypass** 3. **Credential brute-force** ##### Step-by-Step Exploitation --- #### 🧪 Phase 1: Setup + Confirm Behavior 1. **Log in with invalid credentials** - Go to `/login`, submit: ``` username=invaliduser password=invalidpass ``` 2. **Send the request to Burp Repeater** 3. **Add header to bypass IP blocks:** ``` X-Forwarded-For: 127.0.0.1 ``` 4. **Try your own valid credentials (wiener:peter) with a long password** - Observe **increased response time** vs invalid usernames ![[CleanShot 2025-05-07 at 12.59.19.png]] --- #### 🎯 Phase 2: Username Enumeration via Timing 1. **Send request to Burp Intruder** 2. **Set attack type:** `Pitchfork` 3. **Add two payload positions:** - One on `X-Forwarded-For: §IP§` - One on `username=§user§` 4. **Payloads setup:** - **Position 1 (IP spoof):** - Payload type: Numbers (1 to 100, step 1) - This bypasses the rate limit - **Position 2 (Usernames):** - Add the **candidate username list** provided by the lab 5. **Set password to a long string (~100 characters)** to amplify timing difference 6. **Start the attack** 7. **After attack completes:** - Go to `Columns → Show: Response Received`, `Response Completed` - Sort by **response time** - Identify which username consistently takes **longer to respond** ✅ That’s your valid username ![[CleanShot 2025-05-07 at 13.04.39.png]] --- #### 🔓 Phase 3: Password Brute-Force 1. **Create a new Intruder attack on the same login request** 2. **Use `Pitchfork` again** 3. **Payload positions:** - `X-Forwarded-For: §IP§` - `password=§pass§` - Set discovered user 4. **Payloads setup:** - **Position 1:** Numbers 1–100 (IP spoof again) - **Position 2:** Paste candidate password list ![[CleanShot 2025-05-07 at 13.07.06.png]] 5. **Start the attack** 6. **In results:** - Look for response with `302 Found` or length/status difference ✅ That’s the correct password ![[CleanShot 2025-05-07 at 13.06.53.png]] --- #### 🔐 Phase 4: Log In and Solve the Lab - Go to `/login` - Log in as: ``` Username: [discovered-username] Password: [discovered-password] ``` - Access `/my-account` to solve the lab. --- ##### Why It Works - The app uses **timing behavior** (e.g., password hashing or user lookup) that varies for valid vs. invalid usernames. - IP rate limiting is done using actual IPs, but the app **trusts `X-Forwarded-For`** headers — allowing spoofing. - This allows attackers to perform **unrestricted brute-force** using fake IPs. --- ##### Real-World Takeaways - Timing attacks can leak valid usernames even when error messages are generic - IP-based rate limits can be bypassed if the app trusts unvalidated headers - Side channels like response time, status code, and content length are **powerful tools** for breaking auth