Link Search Menu Expand Document

Race Condition

Play SecureFlag Play Labs on this vulnerability with SecureFlag!

  1. Race Condition
    1. Description
    2. Impact
    3. Scenarios
    4. Prevention
    5. Testing

Description

A Race Condition (also known as Time of Check to Time of Use) is a type of attack that exploits the order in which an application carries out a task. Most commonly, the order in which a multi-threaded application performs a task. This allows an attacker to easily manipulate a shared resource to their advantage.

Race Conditions are nearly always caused by poor atomic programming practices. A programmer has attempted to use threads, for example, to handle multiple inbound connections, but has allowed them all to access one resource with no restrictions. However, not all race conditions cause harm; therefore, setting priorities in finding and fixing problematic race conditions is crucial when correcting them.

While Race Conditions can appear in any programming language, some are much more resistant than others. An older programming language, such as C, gives full thread control and memory allocation to the programmer, and is inherently more at risk due to minor mistakes having major complications. However, languages such as Go Lang come with built-in tools such as the race detector, that natively support finding and fixing race conditions. These are much more resistant.

Race Conditions can be hard to find. However, many companies offer continuous bug bounties for them, as many are found once out in production, where an attack could cause significant damage. Static analysis can be used internally to identify possible race conditions before pushing to production.

While not always prominent, race conditions have been around since the first multi-threaded applications. As computer CPUs get more and more multi-threaded and more applications follow suit, race conditions will not be going anywhere.

Impact

Race conditions can wreak internal havoc without even needing a malicious actor present. One of the worst bugs to directly affect human life was the Therac-25 radiotherapy machines. The company produced the software internally without much in the way of checks. After at least three people had died and many more were injured, it was discovered that a race condition was leading the machines to deliver over 100x the correct dose.

Other examples without a malicious actor can be as simple as auto-deployment and CI pipelines, where a simple race condition can incorrectly configure and deploy server tools, interrupting the availability of the pipeline.

Malicious users can use Race Conditions for personal gain. A bug in the nopCommerce platform allowed users to redeem a gift card multiple times, effectively obtaining items for free. Another example is the Reverb attack. Financial or gift card-related attacks like these could cause much greater damage, potentially affecting the integrity of the underlying database.

Scenarios

The simplest race condition is where a call is made to a method, and then another method edits a variable halfway through. For example, a method to subtract five from a number such as x:

def minus_five(x):
  if x > 5: # Some arbitrary check
    y = x - 5

If between x > 5 and y = x - 5, another method comes along and modifies the value of x to below five, it would allow the application to enter an “illegal” state.

The use of locks here could fix this issue by:

# Locking here
def minus_five(x):
  if x > 5: # Some arbitrary check
    y = x - 5
# Unlocking here once complete

Prevention

Prevention of Race Conditions is entirely down to developers. Correct use of atomic programming and locks, when required, can completely mitigate the possibility of this type of attack.

Shared synchronous variables are another way to check to see if the method is already running, using a global variable that, if set, calls a wait until unset by the initial method.

Testing

Most testing of race conditions comes down to built-in tools or community-built plugins to analyze the code and attempt to find them. As mentioned above, static analysis is also valuable for finding possible race conditions.


Table of contents