Tests for race conditions in web applications by sending out a user-specified number of requests to a target URL (or URLs) simultaneously, and then compares the responses from the server for uniqueness. Includes a number of configuration options.
Version 2.0.0 now makes it easier than ever to integrate RTW into your continuous integration pipeline (à la Jenkins, Travis, or Drone), through the use of an easy to use HTTP API. More information can be found in the Usage section below.
Racing the Web - Hackfest 2016
With configuration file
$ race-the-web config.toml
API
$ race-the-web
Example configuration file included (config.toml):
# Sample Configurations
# Send 100 requests to each target
count = 100
# Enable verbose logging
verbose = true
# Use an http proxy for all connections
proxy = "http://127.0.0.1:8080"
# Specify the first request
[[requests]]
# Use the GET request method
method = "GET"
# Set the URL target. Any valid URL is accepted, including ports, https, and parameters.
url = "https://example.com/pay?val=1000"
# Set the request body.
# body = "body=text"
# Set the cookie values to send with the request to this target. Must be an array.
cookies = ["PHPSESSIONID=12345","JSESSIONID=67890"]
# Set custom headers to send with the request to this target. Must be an array.
headers = ["X-Originating-IP: 127.0.0.1", "X-Remote-IP: 127.0.0.1"]
# Follow redirects
redirects = true
# Specify the second request
[[requests]]
# Use the POST request method
method = "POST"
# Set the URL target. Any valid URL is accepted, including ports, https, and parameters.
url = "https://example.com/pay"
# Set the request body.
body = "val=1000"
# Set the cookie values to send with the request to this target. Must be an array.
cookies = ["PHPSESSIONID=ABCDE","JSESSIONID=FGHIJ"]
# Set custom headers to send with the request to this target. Must be an array.
headers = ["X-Originating-IP: 127.0.0.1", "X-Remote-IP: 127.0.0.1"]
# Do not follow redirects
redirects = false
TOML Spec: https://github.com/toml-lang/toml
Since version 2.0.0, RTW now has a full-featured API, which allows you to easily integrate it into your continuous integration (CI) tool of choice. This means that you can quickly and easily test your web application for race conditions automatically whenever you commit your code.
The API works through a simple set of HTTP calls. You provide input in the form of JSON and receive a response in JSON. The 3 API endpoints are as follows:
POST http://127.0.0.1:8000/set/config: Provide configuration data (in JSON format) for the race condition test you want to run (examples below).GET http://127.0.0.1:8000/get/config: Fetch the current configuration data. Data is returned in a JSON response.POST http://127.0.0.1:8000/start: Begin the race condition test using the configuration that you have already provided. All findings are returned back in JSON output./set/config using a POST request){
"count": 100,
"verbose": false,
"requests": [
{
"method": "POST",
"url": "http://racetheweb.io/bank/withdraw",
"cookies": [
"sessionId=dutwJx8kyyfXkt9tZbboT150TjZoFuEZGRy8Mtfpfe7g7UTPybCZX6lgdRkeOjQA"
],
"body": "amount=1",
"redirects": true
}
]
}
Note that this example uses the accompanying website for testing race condition vulnerabilities in web applications, found at RaceTheWeb.io
$ curl -d '{"count":100,"verbose":false,"requests":[{"method":"POST","url":"http://racetheweb.io/bank/withdraw","cookies":["sessionId=Ay2jnxL2TvMnBD2ZF-5bXTXFEldIIBCpcS4FLB-5xjEbDaVnLbf0pPME8DIuNa7-"],"body":"amount=1","redirects":true}]}' -H "Content-Type: application/json" -X POST http://127.0.0.1:8000/set/config
{"message":"configuration saved"}
$ curl -X GET http://127.0.0.1:8000/get/config
{"count":100,"verbose":false,"proxy":"","requests":[{"method":"POST","url":"http://racetheweb.io/bank/withdraw","body":"amount=1","cookies":["sessionId=Ay2jnxL2TvMnBD2ZF-5bXTXFEldIIBCpcS4FLB-5xjEbDaVnLbf0pPME8DIuNa7-"],"headers":null,"redirects":true}]}
$ curl -X POST http://127.0.0.1:8000/start
Response (expanded for visibility):
```JSON [ { "Response": { "Body": "\n<!DOCTYPE html>\n\n \n \n \n \n \n Bank Test\n\n \n \n\n \n \n \n\n \n \n \n \n \n \n \n \n \n
\n\n\n
\n
\n
\n
\n \n
\n
\n
You have successfully withdrawn $1
\n
\n
\n \n \n
\n
\n
\n
\n
\n\n Amount (in dollars)\n
\n
$
\n \n
.00
\n
\n
\n \n
\n
\n
\n\n
\n \n
\n
\n
\n# Make one request\ncount = 100\nverbose = true\n[[requests]]\n method = \"POST\"\n url = \"http://racetheweb.io/bank/withdraw\"\n # Withdraw 1 dollar\n body = \"amount=1\"\n # Insert your sessionId cookie below.\n cookies = [“sessionId=<insert here>\"]\n redirects = false\n\n
\n
\n
\n \n \n \n\n
\n Aaron Hnatiw 2017\n
\n \n \n \n \n \n \n \n\n", "StatusCode": 200, "Length": -1, "Protocol": "HTTP/1.1", "Headers": { "Content-Type": [ "text/html; charset=utf-8" ], "Date": [ "Fri, 18 Aug 2017 15:36:29 GMT" ] }, "Location": "" }, "Targets": [ { "method": "POST", "url": "http://racetheweb.io/bank/withdraw", "body": "amount=1", "cookies": [ "sessionId=Ay2jnxL2TvMnBD2ZF-5bXTXFEldIIBCpcS4FLB-5xjEbDaVnLbf0pPME8DIuNa7-" ], "headers": null, "redirects": true } ], "Count": 1 }, { "Response": { "Body": "\n<!DOCTYPE html>\n\n \n \n \n \n \n Bank Test\n\n \n \n\n \n \n \n\n \n \n \n \n \n \n \n \n \n
\n\n\n
\n
\n
\n
\n \n
\n
\n
You have successfully withdrawn $1
\n
\n
\n \n \n
\n
\n
\n
\n
$ claude mcp add race-the-web \
-- python -m otcore.mcp_server <graph>