Race Conditions
Challenge Lab (Medium) - by Tinus Green
The following post by 0xb0b is licensed under CC BY 4.0
Environment
The diagram below gives a brief idea of how these three websites are interconnected. We have a banking website MWR Bank http://mwrbank.loc, a mobile wallet MWR MOMO http://mwrmomo.loc and a meme swag shop http://mwrswag.loc.

Credentials
Furthermore, the following credentials are provided to us.
Race 1: Transaction Limits - MWR Bank
The first challenge begins with the bank app. We need to authenticate with any given credentials and need to find the arbitrary limit being imposted. We are advised to play arround with the transaction function. We log in as ben.taylor.

We identify the following account numbers, which we will use to perform transactions between them. Our goal is to transfer arbitrary amounts from acfcf96c-5c55-4f02-9c44-449991f49f6b to f66d041f-e264-41dd-9a60-8ccf59d88912 in order to determine whether any transaction limits exist. If such limits are present, we will assess whether they can be bypassed using a race condition that exploits a timing window in the limit-checking logic.
First, we try to transfer an amount that exceeds our limit. We capture the request in Burp Suite and redirect the request to the repeater module.
We see that our transaction is stopped with a message stating that we have an insufficient balance.

Okay, so let's try to execute several transactions at the same time that are below the limit but would exceed our balance in total. We add the tab to a group.

Next, we send the same request to the repeater by right clicking it and chosing that option. Furthermore we edit the amount to 5000 for each request. Next we chose the option to Send the request in the group in parallel (last-byte-sync).
Last-byte sync is a technique where Burp Suite sends almost the entire request but holds back the very last byte of data; once all requests are ready, it releases those final bytes simultaneously to ensure they hit the server at the exact same moment.

We see that both transactions are made.

We reload the page in but do not spot the flag, but a negative balance on f66d041f-e264-41dd-9a60-8ccf59d88912, we exceeded the limit.

If we scroll through the HTTP history in Burp Suite we are able to spot the flag in the response of the request /api/v1.0/account.

Race 2: Account Logon Limit
In Race 2 we are tasked to bypass the logon limit and get access as violet.c. If we have had multiple bad log in request the account gets locked. We remeber the password structure from the given credentials list.
The password structure consists of the prefix pw_, followed by the user's capitalized first name, an exclamation mark, and a two-digit sequential number.
Furthermore we get a hint the account is anywhere between 12-40 on the list of accounts. That might be the two-digit sequential number, the id.
A little hint, this account is anywhere between 12 - 40 on the list of accounts. Remember, you probably only got one shot at this!
So we end up with a password like the following but have only less than 5 tries.
We apply the knowledge gained from the first task and compile a list of request in a group with increasing sequential numbers in the password. Next, we use the Send group in parallel (last-byte sync) option to ensure the requests hit the server simultaneously, aiming to bypass the 'wrong password' increment check before the account lockout triggers.
The numbering of the tabs is arbitrary and based on previous requests in Burp. I recommend trying at least up to sequential number 30 in the password.


We check each request and end up with a valid session token.

Next, we add that token in the browser and refresh the page. We are logged in as violet.c.

As described in the task, we find the flag in the session token. We decode it and find the second flag.

Race 3: Mo Money Mo Limits
In Mo Money Mo Limits, we interact between the banking app and the wallet app. We have the option to transfer money from the banking app to the wallet app. We try to do the same as in the first task and attempt to transfer more money to the wallet than the limit allows. If we succeed, we have the opportunity to generate more money than we possess.
We continue with the user account ben.taylor. We log in to the ben.taylor to the wallet and notice that the account numbers to the bank app are the same.

We make a MoMo transaction that does not exceed our limits, but that is high enough if it is executed twice to exceed the limit. We intercept the request using Burp Suite.

We group the request and generate a duplicate. Afterwards we use the Send group in parallel (last-byte sync) option gain to ensure the requests hit the server simultaneously. We get the flag in the response...

... and see that the wallet receives both transaction even though it exceeded the limits.

Race 4: Shopping Cart Full of Wonder
In Shopping Cart Full of Wonder we are tasked to identfiy the arbitrary limit by ourself.
I had various ideas here, such as paying with other accounts and exploiting the race condition when checking account numbers and passwords. Furthermore I tried multiple checkouts or adding an infinte amount of items to the cart or creating multiple carts, but it was much more simpler.
We proceed with the account kira.patel in this case. Others are valid too.
We note down the credentials and the wallet adress we need to buy items.

We log in as kira.patel on http://mwrswag.log fill up a cart that we can afford with that account and intercept the request and redirect it to the repeater.
The idea is to checkout while adding more items to the cart.
So the cart status goes to paid on the original amount, but we are getting more value by adding more items to the cart that still get shipped to us.

Again we create a group tab. Request one is our checkout. Furthermore we add more items to the cart, but intercept those requests and add them to the tab group exceeding our balance....

...like shown below. We use the Send group in parallel (last-byte sync) option gain to ensure the requests hit the server simultaneously.

And we get the flag in the response...

Race 5: Local Privilege Escalation
Now that we have all the flags, we can use them to form the password and log in to the machine via SSH as lpe. Here we see that we can execute the script /lpe/script.py as root without a password using sudo.

We are not able to edit the script, but we are able to read it.

In short we can see that the script does the following
It reads
/lpe/tmp/script.pyComputes its MD5
Computes MD5 of
/lpe/script.py(the orginial script)It compares the hashes and continues if they match
If they match the script updates itself with the content of
/lpe/tmp/script.py
There is a delay that enabales a TOCTOU (Time-of-Check to Time-of-Use) vulnerability.
Long loop with
sleep(0.001)× 100Expensive math calls
The idea is now to replace the script in /lpe/tmp/script.py with a malicious one after the check has passed.
We create a script that crafts us a SUID bash binary to become root.

We will implement a mechanism to rapidly toggle the file in /lpe/tmp/ between the legitimate and malicious versions to win the race condition. This 'spray and pray' approach relies on the high frequency of swaps to ensure the valid script is present for the hash check and the exploit script is present when the copy command executes.

We run the script...

... and see it got replaced with our malicious one.

Now we run our malicious script and get a SUID bash binary at /tmp/bash.

We run the bash binary and become root. We find the flag at /root/root.txt.

Further Resources
Last updated
Was this helpful?