{"id":13542115,"url":"https://github.com/TheHackerDev/race-the-web","last_synced_at":"2025-04-02T09:33:22.171Z","repository":{"id":37713569,"uuid":"63266951","full_name":"TheHackerDev/race-the-web","owner":"TheHackerDev","description":"Tests for race conditions in web applications. Includes a RESTful API to integrate into a continuous integration pipeline.","archived":false,"fork":false,"pushed_at":"2022-03-18T01:37:41.000Z","size":1813,"stargazers_count":588,"open_issues_count":5,"forks_count":68,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-11-03T07:33:09.373Z","etag":null,"topics":["appsec","devops-tools","infosec","race-conditions","security","security-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheHackerDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-07-13T17:41:29.000Z","updated_at":"2024-10-20T20:57:59.000Z","dependencies_parsed_at":"2022-09-14T19:41:39.675Z","dependency_job_id":null,"html_url":"https://github.com/TheHackerDev/race-the-web","commit_stats":null,"previous_names":["insp3ctre/race-the-web","aaronhnatiw/race-the-web"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheHackerDev%2Frace-the-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheHackerDev%2Frace-the-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheHackerDev%2Frace-the-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheHackerDev%2Frace-the-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheHackerDev","download_url":"https://codeload.github.com/TheHackerDev/race-the-web/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246789178,"owners_count":20834244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appsec","devops-tools","infosec","race-conditions","security","security-tools"],"created_at":"2024-08-01T10:01:01.563Z","updated_at":"2025-04-02T09:33:20.090Z","avatar_url":"https://github.com/TheHackerDev.png","language":"Go","readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/aaronhnatiw/race-the-web)](https://goreportcard.com/report/github.com/aaronhnatiw/race-the-web) [![Build Status](https://travis-ci.org/aaronhnatiw/race-the-web.svg?branch=master)](https://travis-ci.org/aaronhnatiw/race-the-web)\n\n# Race The Web (RTW)\n\nTests 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.\n\n## UPDATE: Now CI Compatible!\n\nVersion 2.0.0 now makes it easier than ever to integrate RTW into your continuous integration pipeline (à la [Jenkins](https://jenkins.io/), [Travis](https://travis-ci.org/), or [Drone](https://github.com/drone/drone)), through the use of an easy to use HTTP API. More information can be found in the **Usage** section below.\n\n## Watch The Talk\n\n[![Racing the Web - Hackfest 2016](https://img.youtube.com/vi/4T99v957I0o/0.jpg)](https://www.youtube.com/watch?v=4T99v957I0o)\n\n_Racing the Web - Hackfest 2016_\n\nSlides: https://www.slideshare.net/AaronHnatiw/racing-the-web-hackfest-2016\n\n## Usage\n\nWith configuration file\n\n```sh\n$ race-the-web config.toml\n```\n\nAPI\n\n```sh\n$ race-the-web\n```\n\n### Configuration File\n\n**Example configuration file included (_config.toml_):**\n\n```toml\n# Sample Configurations\n\n# Send 100 requests to each target\ncount = 100\n# Enable verbose logging\nverbose = true\n# Use an http proxy for all connections\nproxy = \"http://127.0.0.1:8080\"\n\n# Specify the first request\n[[requests]]\n    # Use the GET request method\n    method = \"GET\"\n    # Set the URL target. Any valid URL is accepted, including ports, https, and parameters.\n    url = \"https://example.com/pay?val=1000\"\n    # Set the request body.\n    # body = \"body=text\"\n    # Set the cookie values to send with the request to this target. Must be an array.\n    cookies = [\"PHPSESSIONID=12345\",\"JSESSIONID=67890\"]\n    # Set custom headers to send with the request to this target. Must be an array.\n    headers = [\"X-Originating-IP: 127.0.0.1\", \"X-Remote-IP: 127.0.0.1\"]\n    # Follow redirects\n    redirects = true\n\n# Specify the second request\n[[requests]]\n    # Use the POST request method\n    method = \"POST\"\n    # Set the URL target. Any valid URL is accepted, including ports, https, and parameters.\n    url = \"https://example.com/pay\"\n    # Set the request body.\n    body = \"val=1000\"\n    # Set the cookie values to send with the request to this target. Must be an array.\n    cookies = [\"PHPSESSIONID=ABCDE\",\"JSESSIONID=FGHIJ\"]\n    # Set custom headers to send with the request to this target. Must be an array.\n    headers = [\"X-Originating-IP: 127.0.0.1\", \"X-Remote-IP: 127.0.0.1\"]\n    # Do not follow redirects\n    redirects = false\n```\n\nTOML Spec: https://github.com/toml-lang/toml\n\n### API\n\nSince 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.\n\nThe 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:\n\n- `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).\n- `GET` `http://127.0.0.1:8000/get/config`: Fetch the current configuration data. Data is returned in a JSON response.\n- `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.\n\n#### Example JSON configuration (sent to `/set/config` using a `POST` request)\n\n```json\n{\n    \"count\": 100,\n    \"verbose\": false,\n    \"requests\": [\n        {\n            \"method\": \"POST\",\n            \"url\": \"http://racetheweb.io/bank/withdraw\",\n            \"cookies\": [\n                \"sessionId=dutwJx8kyyfXkt9tZbboT150TjZoFuEZGRy8Mtfpfe7g7UTPybCZX6lgdRkeOjQA\"\n            ],\n            \"body\": \"amount=1\",\n            \"redirects\": true\n        }\n    ]\n}\n```\n\n#### Example workflow using curl\n\n\n1. Send the configuration data\n\n```sh\n$ 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\n\n{\"message\":\"configuration saved\"}\n```\n\n2. Retrieve the configuration data for validation\n\n```sh\n$ curl -X GET http://127.0.0.1:8000/get/config\n\n{\"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}]}\n```\n\n3. Start the race condition test\n\n```sh\n$ curl -X POST http://127.0.0.1:8000/start\n```\n\nResponse (expanded for visibility):\n\n```JSON\n[\n    {\n        \"Response\": {\n            \"Body\": \"\\n\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n  \u003chead\u003e\\n    \u003cmeta charset=\\\"utf-8\\\"\u003e\\n    \u003cmeta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\"\u003e\\n    \u003cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1\\\"\u003e\\n    \\n    \u003ctitle\u003eBank Test\u003c/title\u003e\\n\\n    \\n    \u003clink href=\\\"/static/css/bootstrap.min.css\\\" rel=\\\"stylesheet\\\"\u003e\\n\\n    \\n    \\n    \\n\\n    \\n    \u003cmeta name=\\\"twitter:card\\\" content=\\\"summary_large_image\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:site\\\" content=\\\"@insp3ctre\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:title\\\" content=\\\"Race Condition Exploit Practice\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:description\\\" content=\\\"Learn how to exploit race conditions in web applications.\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:image\\\" content=\\\"/static/img/bank_homepage_screenshot_wide.png\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:image:alt\\\" content=\\\"Image of the bank account exploit application.\\\" /\u003e\\n  \u003c/head\u003e\\n  \u003cbody\u003e\\n    \u003cnav class=\\\"navbar\\\"\u003e\\n      \u003cdiv class=\\\"container-fluid\\\"\u003e\\n        \u003cdiv class=\\\"navbar-header\\\"\u003e\\n          \u003ca class=\\\"navbar-brand\\\" href=\\\"/\\\"\u003eRace-The-Web\u003c/a\u003e\\n        \u003c/div\u003e\\n        \u003cul class=\\\"nav navbar-nav\\\"\u003e\\n          \u003cli\u003e\u003ca href=\\\"/bank\\\"\u003eBank\u003c/a\u003e\u003c/li\u003e\\n        \u003c/ul\u003e\\n        \u003cul class=\\\"nav navbar-nav navbar-right\\\"\u003e\\n          \u003cli\u003e\u003ca href=\\\"https://www.youtube.com/watch?v=4T99v957I0o\\\"\u003e\u003cimg src=\\\"http://racetheweb.io/static/img/logo-youtube.png\\\" alt=\\\"Racing the Web - Hackfest 2016\\\" title=\\\"Racing the Web - Hackfest 2016\\\"\u003e\u003c/a\u003e\u003c/li\u003e\\n          \u003cli\u003e\u003ca href=\\\"https://github.com/insp3ctre/race-the-web\\\"\u003e\u003cimg src=\\\"/static/img/logo-github.png\\\" alt=\\\"Race-The-Web on Github\\\"\u003e\u003c/a\u003e\u003c/li\u003e\\n        \u003c/ul\u003e\\n      \u003c/div\u003e\\n    \u003c/nav\u003e\\n\\n    \u003cdiv class=\\\"container\\\"\u003e\\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"page-header\\\"\u003e\\n                \u003ch1 class=\\\"text-center\\\"\u003eWelcome to SpeedBank, International\u003c/h1\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-12 col-sm-8 col-sm-offset-2\\\"\u003e\\n                \u003cp class=\\\"text-center bg-success\\\"\u003eYou have successfully withdrawn $1\u003c/p\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003ch2 class=\\\"text-center\\\"\u003eBalance: 9999\u003c/h2\u003e\\n        \u003c/div\u003e\\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-8 col-xs-offset-3\\\"\u003e\\n                \u003cform action=\\\"/bank/withdraw\\\" method=\\\"POST\\\" class=\\\"form-inline\\\"\u003e\\n                    \u003cdiv class=\\\"form-group\\\"\u003e\\n                        \u003clabel class=\\\"sr-only\\\" for=\\\"withdrawAmount\\\"\u003eAmount (in dollars)\u003c/label\u003e\\n                        \u003cdiv class=\\\"input-group\\\"\u003e\\n                            \u003cdiv class=\\\"input-group-addon\\\"\u003e$\u003c/div\u003e\\n                            \u003cinput type=\\\"text\\\" class=\\\"form-control\\\" id=\\\"withdrawAmount\\\" name=\\\"amount\\\" placeholder=\\\"Amount\\\"\u003e\\n                            \u003cdiv class=\\\"input-group-addon\\\"\u003e.00\u003c/div\u003e\\n                        \u003c/div\u003e\\n                        \u003cdiv class=\\\"input-group\\\"\u003e\\n                            \u003cinput type=\\\"submit\\\" class=\\\"btn btn-primary\\\" value=\\\"Withdraw cash\\\"\u003e\\n                        \u003c/div\u003e\\n                    \u003c/div\u003e\\n                \u003c/form\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-12 col-sm-8 col-sm-offset-2\\\"\u003e\\n                \u003ch2 class=\\\"text-center\\\"\u003eInstructions\u003c/h2\u003e\\n                \u003col\u003e\\n                    \u003cli\u003eClick “Initialize” to initialize a bank account with $10,000.\u003c/li\u003e\\n                    \u003cli\u003eWithdraw money from your account, observe that your account balance is updated, and that you have received the amount requested.\u003c/li\u003e\\n                    \u003cli\u003eRepeat the request with \u003ca href=\\\"https://github.com/insp3ctre/race-the-web\\\"\u003erace-the-web\u003c/a\u003e. Your config file should look like the following:\u003c/li\u003e\\n\u003cpre\u003e\\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=\u0026lt;insert here\u0026gt;\\\"]\\n    redirects = false\\n\u003c/pre\u003e\\n                    \u003cli\u003eVisit the bank page again in your browser to view your updated balance. Note that the total \u003cem\u003eshould\u003c/em\u003e be $100 less ($1 * 100 requests) than when you originally withdrew money. However, due to a race condition flaw in the application, your balance will be much more, yet you will have received the money from the bank in every withdrawal.\u003c/li\u003e\\n                \u003c/ol\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n    \u003c/div\u003e\\n    \\n    \u003cscript type=\\\"text/javascript\\\"\u003e\\n        \\n        history.replaceState(\\\"Bank\\\", \\\"Bank\\\", \\\"/bank\\\")\\n    \u003c/script\u003e\\n    \\n\\n    \u003cp class=\\\"small text-center\\\"\u003e\\n        \u003cspan class=\\\"glyphicon glyphicon-copyright-mark\\\" aria-hidden=\\\"true\\\"\u003e\u003c/span\u003e\u003ca href=\\\"https://www.twitter.com/insp3ctre\\\"\u003eAaron Hnatiw\u003c/a\u003e 2017\\n    \u003c/p\u003e\\n    \\n    \u003cscript src=\\\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\\\"\u003e\u003c/script\u003e\\n    \\n    \u003cscript src=\\\"/static/js/bootstrap.min.js\\\"\u003e\u003c/script\u003e\\n    \\n    \u003cscript\u003e\\n    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\\n    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\\n    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\\n    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\\n\\n    ga('create', 'UA-93555669-1', 'auto');\\n    ga('send', 'pageview');\\n\\n    \u003c/script\u003e\\n    \u003c/body\u003e\\n\u003c/html\u003e\\n\",\n            \"StatusCode\": 200,\n            \"Length\": -1,\n            \"Protocol\": \"HTTP/1.1\",\n            \"Headers\": {\n                \"Content-Type\": [\n                    \"text/html; charset=utf-8\"\n                ],\n                \"Date\": [\n                    \"Fri, 18 Aug 2017 15:36:29 GMT\"\n                ]\n            },\n            \"Location\": \"\"\n        },\n        \"Targets\": [\n            {\n                \"method\": \"POST\",\n                \"url\": \"http://racetheweb.io/bank/withdraw\",\n                \"body\": \"amount=1\",\n                \"cookies\": [\n                    \"sessionId=Ay2jnxL2TvMnBD2ZF-5bXTXFEldIIBCpcS4FLB-5xjEbDaVnLbf0pPME8DIuNa7-\"\n                ],\n                \"headers\": null,\n                \"redirects\": true\n            }\n        ],\n        \"Count\": 1\n    },\n    {\n        \"Response\": {\n            \"Body\": \"\\n\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n  \u003chead\u003e\\n    \u003cmeta charset=\\\"utf-8\\\"\u003e\\n    \u003cmeta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\"\u003e\\n    \u003cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1\\\"\u003e\\n    \\n    \u003ctitle\u003eBank Test\u003c/title\u003e\\n\\n    \\n    \u003clink href=\\\"/static/css/bootstrap.min.css\\\" rel=\\\"stylesheet\\\"\u003e\\n\\n    \\n    \\n    \\n\\n    \\n    \u003cmeta name=\\\"twitter:card\\\" content=\\\"summary_large_image\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:site\\\" content=\\\"@insp3ctre\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:title\\\" content=\\\"Race Condition Exploit Practice\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:description\\\" content=\\\"Learn how to exploit race conditions in web applications.\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:image\\\" content=\\\"/static/img/bank_homepage_screenshot_wide.png\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:image:alt\\\" content=\\\"Image of the bank account exploit application.\\\" /\u003e\\n  \u003c/head\u003e\\n  \u003cbody\u003e\\n    \u003cnav class=\\\"navbar\\\"\u003e\\n      \u003cdiv class=\\\"container-fluid\\\"\u003e\\n        \u003cdiv class=\\\"navbar-header\\\"\u003e\\n          \u003ca class=\\\"navbar-brand\\\" href=\\\"/\\\"\u003eRace-The-Web\u003c/a\u003e\\n        \u003c/div\u003e\\n        \u003cul class=\\\"nav navbar-nav\\\"\u003e\\n          \u003cli\u003e\u003ca href=\\\"/bank\\\"\u003eBank\u003c/a\u003e\u003c/li\u003e\\n        \u003c/ul\u003e\\n        \u003cul class=\\\"nav navbar-nav navbar-right\\\"\u003e\\n          \u003cli\u003e\u003ca href=\\\"https://www.youtube.com/watch?v=4T99v957I0o\\\"\u003e\u003cimg src=\\\"http://racetheweb.io/static/img/logo-youtube.png\\\" alt=\\\"Racing the Web - Hackfest 2016\\\" title=\\\"Racing the Web - Hackfest 2016\\\"\u003e\u003c/a\u003e\u003c/li\u003e\\n          \u003cli\u003e\u003ca href=\\\"https://github.com/insp3ctre/race-the-web\\\"\u003e\u003cimg src=\\\"/static/img/logo-github.png\\\" alt=\\\"Race-The-Web on Github\\\"\u003e\u003c/a\u003e\u003c/li\u003e\\n        \u003c/ul\u003e\\n      \u003c/div\u003e\\n    \u003c/nav\u003e\\n\\n    \u003cdiv class=\\\"container\\\"\u003e\\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"page-header\\\"\u003e\\n                \u003ch1 class=\\\"text-center\\\"\u003eWelcome to SpeedBank, International\u003c/h1\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-12 col-sm-8 col-sm-offset-2\\\"\u003e\\n                \u003cp class=\\\"text-center bg-success\\\"\u003eYou have successfully withdrawn $1\u003c/p\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003ch2 class=\\\"text-center\\\"\u003eBalance: 9998\u003c/h2\u003e\\n        \u003c/div\u003e\\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-8 col-xs-offset-3\\\"\u003e\\n                \u003cform action=\\\"/bank/withdraw\\\" method=\\\"POST\\\" class=\\\"form-inline\\\"\u003e\\n                    \u003cdiv class=\\\"form-group\\\"\u003e\\n                        \u003clabel class=\\\"sr-only\\\" for=\\\"withdrawAmount\\\"\u003eAmount (in dollars)\u003c/label\u003e\\n                        \u003cdiv class=\\\"input-group\\\"\u003e\\n                            \u003cdiv class=\\\"input-group-addon\\\"\u003e$\u003c/div\u003e\\n                            \u003cinput type=\\\"text\\\" class=\\\"form-control\\\" id=\\\"withdrawAmount\\\" name=\\\"amount\\\" placeholder=\\\"Amount\\\"\u003e\\n                            \u003cdiv class=\\\"input-group-addon\\\"\u003e.00\u003c/div\u003e\\n                        \u003c/div\u003e\\n                        \u003cdiv class=\\\"input-group\\\"\u003e\\n                            \u003cinput type=\\\"submit\\\" class=\\\"btn btn-primary\\\" value=\\\"Withdraw cash\\\"\u003e\\n                        \u003c/div\u003e\\n                    \u003c/div\u003e\\n                \u003c/form\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-12 col-sm-8 col-sm-offset-2\\\"\u003e\\n                \u003ch2 class=\\\"text-center\\\"\u003eInstructions\u003c/h2\u003e\\n                \u003col\u003e\\n                    \u003cli\u003eClick “Initialize” to initialize a bank account with $10,000.\u003c/li\u003e\\n                    \u003cli\u003eWithdraw money from your account, observe that your account balance is updated, and that you have received the amount requested.\u003c/li\u003e\\n                    \u003cli\u003eRepeat the request with \u003ca href=\\\"https://github.com/insp3ctre/race-the-web\\\"\u003erace-the-web\u003c/a\u003e. Your config file should look like the following:\u003c/li\u003e\\n\u003cpre\u003e\\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=\u0026lt;insert here\u0026gt;\\\"]\\n    redirects = false\\n\u003c/pre\u003e\\n                    \u003cli\u003eVisit the bank page again in your browser to view your updated balance. Note that the total \u003cem\u003eshould\u003c/em\u003e be $100 less ($1 * 100 requests) than when you originally withdrew money. However, due to a race condition flaw in the application, your balance will be much more, yet you will have received the money from the bank in every withdrawal.\u003c/li\u003e\\n                \u003c/ol\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n    \u003c/div\u003e\\n    \\n    \u003cscript type=\\\"text/javascript\\\"\u003e\\n        \\n        history.replaceState(\\\"Bank\\\", \\\"Bank\\\", \\\"/bank\\\")\\n    \u003c/script\u003e\\n    \\n\\n    \u003cp class=\\\"small text-center\\\"\u003e\\n        \u003cspan class=\\\"glyphicon glyphicon-copyright-mark\\\" aria-hidden=\\\"true\\\"\u003e\u003c/span\u003e\u003ca href=\\\"https://www.twitter.com/insp3ctre\\\"\u003eAaron Hnatiw\u003c/a\u003e 2017\\n    \u003c/p\u003e\\n    \\n    \u003cscript src=\\\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\\\"\u003e\u003c/script\u003e\\n    \\n    \u003cscript src=\\\"/static/js/bootstrap.min.js\\\"\u003e\u003c/script\u003e\\n    \\n    \u003cscript\u003e\\n    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\\n    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\\n    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\\n    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\\n\\n    ga('create', 'UA-93555669-1', 'auto');\\n    ga('send', 'pageview');\\n\\n    \u003c/script\u003e\\n    \u003c/body\u003e\\n\u003c/html\u003e\\n\",\n            \"StatusCode\": 200,\n            \"Length\": -1,\n            \"Protocol\": \"HTTP/1.1\",\n            \"Headers\": {\n                \"Content-Type\": [\n                    \"text/html; charset=utf-8\"\n                ],\n                \"Date\": [\n                    \"Fri, 18 Aug 2017 15:36:30 GMT\"\n                ]\n            },\n            \"Location\": \"\"\n        },\n        \"Targets\": [\n            {\n                \"method\": \"POST\",\n                \"url\": \"http://racetheweb.io/bank/withdraw\",\n                \"body\": \"amount=1\",\n                \"cookies\": [\n                    \"sessionId=Ay2jnxL2TvMnBD2ZF-5bXTXFEldIIBCpcS4FLB-5xjEbDaVnLbf0pPME8DIuNa7-\"\n                ],\n                \"headers\": null,\n                \"redirects\": true\n            }\n        ],\n        \"Count\": 1\n    },\n    {\n        \"Response\": {\n            \"Body\": \"\\n\u003c!DOCTYPE html\u003e\\n\u003chtml lang=\\\"en\\\"\u003e\\n  \u003chead\u003e\\n    \u003cmeta charset=\\\"utf-8\\\"\u003e\\n    \u003cmeta http-equiv=\\\"X-UA-Compatible\\\" content=\\\"IE=edge\\\"\u003e\\n    \u003cmeta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1\\\"\u003e\\n    \\n    \u003ctitle\u003eBank Test\u003c/title\u003e\\n\\n    \\n    \u003clink href=\\\"/static/css/bootstrap.min.css\\\" rel=\\\"stylesheet\\\"\u003e\\n\\n    \\n    \\n    \\n\\n    \\n    \u003cmeta name=\\\"twitter:card\\\" content=\\\"summary_large_image\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:site\\\" content=\\\"@insp3ctre\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:title\\\" content=\\\"Race Condition Exploit Practice\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:description\\\" content=\\\"Learn how to exploit race conditions in web applications.\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:image\\\" content=\\\"/static/img/bank_homepage_screenshot_wide.png\\\" /\u003e\\n    \u003cmeta name=\\\"twitter:image:alt\\\" content=\\\"Image of the bank account exploit application.\\\" /\u003e\\n  \u003c/head\u003e\\n  \u003cbody\u003e\\n    \u003cnav class=\\\"navbar\\\"\u003e\\n      \u003cdiv class=\\\"container-fluid\\\"\u003e\\n        \u003cdiv class=\\\"navbar-header\\\"\u003e\\n          \u003ca class=\\\"navbar-brand\\\" href=\\\"/\\\"\u003eRace-The-Web\u003c/a\u003e\\n        \u003c/div\u003e\\n        \u003cul class=\\\"nav navbar-nav\\\"\u003e\\n          \u003cli\u003e\u003ca href=\\\"/bank\\\"\u003eBank\u003c/a\u003e\u003c/li\u003e\\n        \u003c/ul\u003e\\n        \u003cul class=\\\"nav navbar-nav navbar-right\\\"\u003e\\n          \u003cli\u003e\u003ca href=\\\"https://www.youtube.com/watch?v=4T99v957I0o\\\"\u003e\u003cimg src=\\\"http://racetheweb.io/static/img/logo-youtube.png\\\" alt=\\\"Racing the Web - Hackfest 2016\\\" title=\\\"Racing the Web - Hackfest 2016\\\"\u003e\u003c/a\u003e\u003c/li\u003e\\n          \u003cli\u003e\u003ca href=\\\"https://github.com/insp3ctre/race-the-web\\\"\u003e\u003cimg src=\\\"/static/img/logo-github.png\\\" alt=\\\"Race-The-Web on Github\\\"\u003e\u003c/a\u003e\u003c/li\u003e\\n        \u003c/ul\u003e\\n      \u003c/div\u003e\\n    \u003c/nav\u003e\\n\\n    \u003cdiv class=\\\"container\\\"\u003e\\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"page-header\\\"\u003e\\n                \u003ch1 class=\\\"text-center\\\"\u003eWelcome to SpeedBank, International\u003c/h1\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-12 col-sm-8 col-sm-offset-2\\\"\u003e\\n                \u003cp class=\\\"text-center bg-success\\\"\u003eYou have successfully withdrawn $1\u003c/p\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003ch2 class=\\\"text-center\\\"\u003eBalance: 9997\u003c/h2\u003e\\n        \u003c/div\u003e\\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-8 col-xs-offset-3\\\"\u003e\\n                \u003cform action=\\\"/bank/withdraw\\\" method=\\\"POST\\\" class=\\\"form-inline\\\"\u003e\\n                    \u003cdiv class=\\\"form-group\\\"\u003e\\n                        \u003clabel class=\\\"sr-only\\\" for=\\\"withdrawAmount\\\"\u003eAmount (in dollars)\u003c/label\u003e\\n                        \u003cdiv class=\\\"input-group\\\"\u003e\\n                            \u003cdiv class=\\\"input-group-addon\\\"\u003e$\u003c/div\u003e\\n                            \u003cinput type=\\\"text\\\" class=\\\"form-control\\\" id=\\\"withdrawAmount\\\" name=\\\"amount\\\" placeholder=\\\"Amount\\\"\u003e\\n                            \u003cdiv class=\\\"input-group-addon\\\"\u003e.00\u003c/div\u003e\\n                        \u003c/div\u003e\\n                        \u003cdiv class=\\\"input-group\\\"\u003e\\n                            \u003cinput type=\\\"submit\\\" class=\\\"btn btn-primary\\\" value=\\\"Withdraw cash\\\"\u003e\\n                        \u003c/div\u003e\\n                    \u003c/div\u003e\\n                \u003c/form\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n        \\n        \u003cdiv class=\\\"row\\\"\u003e\\n            \u003cdiv class=\\\"col-xs-12 col-sm-8 col-sm-offset-2\\\"\u003e\\n                \u003ch2 class=\\\"text-center\\\"\u003eInstructions\u003c/h2\u003e\\n                \u003col\u003e\\n                    \u003cli\u003eClick “Initialize” to initialize a bank account with $10,000.\u003c/li\u003e\\n                    \u003cli\u003eWithdraw money from your account, observe that your account balance is updated, and that you have received the amount requested.\u003c/li\u003e\\n                    \u003cli\u003eRepeat the request with \u003ca href=\\\"https://github.com/insp3ctre/race-the-web\\\"\u003erace-the-web\u003c/a\u003e. Your config file should look like the following:\u003c/li\u003e\\n\u003cpre\u003e\\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=\u0026lt;insert here\u0026gt;\\\"]\\n    redirects = false\\n\u003c/pre\u003e\\n                    \u003cli\u003eVisit the bank page again in your browser to view your updated balance. Note that the total \u003cem\u003eshould\u003c/em\u003e be $100 less ($1 * 100 requests) than when you originally withdrew money. However, due to a race condition flaw in the application, your balance will be much more, yet you will have received the money from the bank in every withdrawal.\u003c/li\u003e\\n                \u003c/ol\u003e\\n            \u003c/div\u003e\\n        \u003c/div\u003e\\n    \u003c/div\u003e\\n    \\n    \u003cscript type=\\\"text/javascript\\\"\u003e\\n        \\n        history.replaceState(\\\"Bank\\\", \\\"Bank\\\", \\\"/bank\\\")\\n    \u003c/script\u003e\\n    \\n\\n    \u003cp class=\\\"small text-center\\\"\u003e\\n        \u003cspan class=\\\"glyphicon glyphicon-copyright-mark\\\" aria-hidden=\\\"true\\\"\u003e\u003c/span\u003e\u003ca href=\\\"https://www.twitter.com/insp3ctre\\\"\u003eAaron Hnatiw\u003c/a\u003e 2017\\n    \u003c/p\u003e\\n    \\n    \u003cscript src=\\\"https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js\\\"\u003e\u003c/script\u003e\\n    \\n    \u003cscript src=\\\"/static/js/bootstrap.min.js\\\"\u003e\u003c/script\u003e\\n    \\n    \u003cscript\u003e\\n    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\\n    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\\n    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\\n    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');\\n\\n    ga('create', 'UA-93555669-1', 'auto');\\n    ga('send', 'pageview');\\n\\n    \u003c/script\u003e\\n    \u003c/body\u003e\\n\u003c/html\u003e\\n\",\n            \"StatusCode\": 200,\n            \"Length\": -1,\n            \"Protocol\": \"HTTP/1.1\",\n            \"Headers\": {\n                \"Content-Type\": [\n                    \"text/html; charset=utf-8\"\n                ],\n                \"Date\": [\n                    \"Fri, 18 Aug 2017 15:36:36 GMT\"\n                ]\n            },\n            \"Location\": \"\"\n        },\n        \"Targets\": [\n            {\n                \"method\": \"POST\",\n                \"url\": \"http://racetheweb.io/bank/withdraw\",\n                \"body\": \"amount=1\",\n                \"cookies\": [\n                    \"sessionId=Ay2jnxL2TvMnBD2ZF-5bXTXFEldIIBCpcS4FLB-5xjEbDaVnLbf0pPME8DIuNa7-\"\n                ],\n                \"headers\": null,\n                \"redirects\": true\n            }\n        ],\n        \"Count\": 98\n    }\n]\n```\n\n## Binaries\n\nThe program has been written in Go, and as such can be compiled to all the common platforms in use today. The following architectures have been compiled, and can be found in the [releases](https://github.com/insp3ctre/race-the-web/releases) tab:\n\n- Windows amd64\n- Windows 386\n- Linux amd64\n- Linux 386\n- OSX amd64\n- OSX 386\n\n## Compiling\n\nFirst, make sure you have Go installed on your system. If you don't you can follow the install instructions for your operating system of choice here: https://golang.org/doc/install.\n\nBuild a binary for your current CPU architecture\n\n```sh\n$ make build\n```\n\nBuild for all major CPU architectures (see [Makefile](https://github.com/insp3ctre/race-the-web/blob/master/Makefile) for details) at once\n\n```sh\n$ make\n```\n\n### Dep\n\nThis project uses [Dep](https://github.com/golang/dep) for dependency management. All of the required files are kept in the `vendor` directory, however if you are getting errors related to dependencies, simply download Dep\n\n```sh\n$ go get -u github.com/golang/dep/cmd/dep\n```\n\nand run the following command from the RTW directory in order to download all dependencies\n\n```sh\n$ dep ensure\n```\n\n### Go 1.7 and newer are supported\n\nBefore 1.7, the `encoding/json` package's `Encoder` did not have a method to escape the `\u0026`, `\u003c`, and `\u003e` characters; this is required in order to have a clean output of full HTML pages when running these race tests. _If this is an issue for your test cases, please submit a [new issue](https://github.com/insp3ctre/race-the-web/issues) indicating as such, and I will add a workaround (just note that any output from a server with those characters will come back with unicode escapes instead)._ Here are the relevant release details from Go 1.7: https://golang.org/doc/go1.7#encoding_json.\n\n## The Vulnerability\n\n\u003e A race condition is a flaw that produces an unexpected result when the timing of actions impact other actions. An example may be seen on a multithreaded application where actions are being performed on the same data. Race conditions, by their very nature, are difficult to test for.\n\u003e - [OWASP](https://www.owasp.org/index.php/Testing_for_Race_Conditions_(OWASP-AT-010))\n\nRace conditions are a well known issue in software development, especially when you deal with fast, multi-threaded languages.\n\nHowever, as network speeds get faster and faster, web applications are becoming increasingly vulnerable to race conditions. Often because of legacy code that was not created to handle hundreds or thousands of simultaneous requests for the same function or resource.\n\nThe problem can often only be discovered when a fast, multi-threaded language is being used to generate these requests, using a fast network connection; at which point it becomes a network and logic race between the client application and the server application.\n\nThat is where **Race The Web** comes in. This program aims to discover race conditions in web applications by sending a large amount of requests to a specific endpoint at the same time. By doing so, it may invoke unintended behaviour on the server, such as the duplication of user information, coupon codes, bitcoins, etc.\n\n**Warning:** Denial of service may be an unintended side-effect of using this application, so please be careful when using it, and always perform this kind of testing with the explicit permission of the server owner and web application owner.\n\nCredit goes to [Josip Franjković](https://twitter.com/josipfranjkovic) for his [excellent article on the subject](https://www.josipfranjkovic.com/blog/race-conditions-on-web), which introduced me to this problem.\n\n## Why Go\n\nThe [Go programming language](https://golang.org/) is perfectly suited for the task, mainly because it is *so damned fast*. Here are a few reasons why:\n\n- Concurrency: Concurrency primitives are built into the language itself, and extremely easy to add to any Go program. Threading is [handled by the Go runtime scheduler](https://morsmachine.dk/go-scheduler), and not by the underlying operating system, which allows for some serious performance optimizations when it comes to concurrency.\n- Compiled: *Cross-compiles* to [most modern operating systems](https://golang.org/doc/install/source#environment); not slowed down by an interpreter or virtual machine middle-layer ([here are some benchmarks vs Java](https://benchmarksgame.alioth.debian.org/u64q/go.html)). (Oh, and did I mention that the binaries are statically compiled?)\n- Lightweight: Only [25 keywords](https://golang.org/ref/spec#Keywords) in the language, and yet still almost everything can be done using the standard library.\n\nFor more of the nitty-gritty details on why Go is so fast, see [Dave Cheney](https://twitter.com/davecheney)'s [excellent talk on the subject](http://dave.cheney.net/2014/06/07/five-things-that-make-go-fast), from 2014.\n","funding_links":[],"categories":["Weapons","Exploitation"],"sub_categories":["Tools","Race Condition"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTheHackerDev%2Frace-the-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTheHackerDev%2Frace-the-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTheHackerDev%2Frace-the-web/lists"}