Secure coding

How to exploit race conditions

January 4, 2021 by Howard Poston

Race conditions vulnerabilities can exist in applications that contain parallel processing. These vulnerabilities exist if multiple threads of execution do not interact with shared resources in a safe manner.

For example, an application containing a race condition vulnerability may have multiple threads accessing and removing elements from a shared vector. If this is the case and the application is not designed to be threadsafe, an array out-of-bound error may occur if a thread reads from an empty vector that it thought still contained at least one element.

Exploiting race condition vulnerabilities

Race condition vulnerabilities make an application potentially vulnerable to exploitation. This is true even if the application is not designed to be parallelized but makes use of shared resources on the computer (files and so on).

Running multiple applications in parallel

Not all applications are designed to be multithreaded. Those that are designed in this way are more likely to be designed and implemented in a threadsafe fashion, since the developer is actively thinking about parallel processing when planning and writing the code.

However, the fact that an application is not designed to be run in a parallelized fashion doesn’t mean that it can’t be. In addition to multithreading, parallel processing can occur at the process level if multiple different instances of the same application are run in parallel.

At the process level, far less is shared between different threads of execution than in a multithreaded program. However, low-level resources like the file system, peripherals and so on are shared between multiple different processes on the system.

By running multiple different instances of an application at the same time, an attacker may be able to take advantage of a race condition vulnerability that impacts these low-level components. This could cause the multiple processes to compete in a way that the developer did not anticipate and that might undermine the application’s security.

Programmatic access to an application

Supporting multiple users at once is a common use of parallel processing within an application. Each request is handled by a separate thread of execution, making it possible for the application to truly support multiple users at once.

If an application is designed in this way but not in a threadsafe fashion, then programmatic access to the application may allow an attacker to exploit a race condition vulnerability. In many cases, race conditions have a very small window for exploitation, making them difficult or impossible for a human to exploit the vulnerability. However, the use of an automated bot to interact with the application may be able to make requests close enough together to cause different threads of execution to run closely enough together to exploit the race condition vulnerability.

Using an external program to edit shared resources

Some applications are designed to use files — either temporary or permanent — to store state and data. For example, an application may store user account information in a database or write the results of a particular operation to a temporary file for future reference.

Depending upon the details of the algorithm’s implementation and permissions, this may make the application vulnerable to exploitation. Files stored on a computer’s filesystem are accessible to any application or user with the appropriate permissions. If an application manages to gain access to and modify a temporary file between an application’s initial write to the file and later read or between checking its contents and reading them in for use (time-of-check time-of-use race condition), then they may be able to control the application’s operations or gain additional permissions on the system.

Taking advantage of race condition vulnerabilities

Race condition vulnerabilities are most obvious if they exist because a multithreaded application is not implemented in a threadsafe manner. However, these vulnerabilities can also exist and be exploited if an application not designed to be parallelized makes use of low-level resources in an unsafe manner. All applications using shared resources need to be designed in a way that they do not trust in the integrity of these shared, untrusted resources.

 

Sources

  1. Race Condition, AppSec Knowledge Base
  2. Time of check to time of use (TOCTOU): A race condition, Hacker Noon
  3. POSIX Threads, csc.villanova.edu
Posted: January 4, 2021
Articles Author
Howard Poston
View Profile

Howard Poston is a cybersecurity researcher with a background in cryptography and malware analysis. He has a Master’s degree in Cyber Operations from the Air Force Institute of Technology and two years of experience in cybersecurity R&D at Sandia National Labs. He currently provides consulting and technical content writing for cybersecurity, cryptocurrency, and blockchain.