What is a race condition?
A race condition is unacceptable when a device or system seeks to simultaneously conduct two or more operations. However, the activities must still be performed in the proper sequence depending upon the nature of the device or system.
They arise when two processes, or threads of software programs, attempt to access the same resource simultaneously, causing system problems.
Race situations are a prevalent problem in multithreaded programs. Race condition vulnerability occurs in both web applications as well as mobile applications.
What is a race condition vulnerability?
Race condition attacks are also known as Time of Check to Time of Use (TOCTTOU) attacks. Attackers take advantage of performing specific activities in a specified order.
The system completes the first job or process in sequence but does not begin the second.
The name of the vulnerability according to Common Enumeration Weakness: “Concurrent Execution using Shared Resource with Improper Synchronization (‘Race Condition’)” with the ID is CWE-362.
Reasons for Race conditions:
- If the process is taking more time to finish the tasks
- If the attacker is lucky and skilled
For both reasons, as mentioned above, a race situation vulnerability occurs, allowing the attacker to deceive the system into doing illegal operations in addition to its usual processes.
This attack can be carried out in two ways:
Untrusted process: The attacker inserts code between the phases of a secure method.
Trusted process: The attacker takes advantage of two different procedures that share a particular stage.
Types of race conditions
There are two types of race conditions that exist.
- Critical: A critical race condition will cause the device, system, or program’s final phase. For example, if simultaneously switching two light switches linked to a standard light breaks the circuit, this is a critical race condition. A critical race condition in software occurs when a circumstance results in a bug with unexpected or undefined behavior.
- Non-critical: A non-critical race condition has no direct impact on the system, device, or program’s final phase. In the above example, if the light is turned off and simultaneously turns the light on by turning both switches and has the same impact as flipping one switch. This is a non-critical race situation. A non-critical race condition in software does not result in a bug.
Computer programming isn’t the only area where critical and non-critical race situations exist. They can arise in a variety of systems where race conditions exist.
In programming, two types of race situations might arise in a significant element of code, which is code executed by many threads. When many threads attempt to read the same variable and subsequently act on it, one of the following scenarios can occur:
Read-modify-write: A race condition occurs when two processes receive a value from a program and write back a new value or data. It frequently results in a software bug. As in the preceding example, the assumption is that the two processes would occur sequentially:
- The first process generates its value and
- The second process reads that value and returns a new one.
Check-then-act: A race situation occurs when two processes examine a value on which they will each execute an external action. Both programs verify the value, but only one may accept the value. The value will be viewed as null by the subsequent procedure. As a result, an observation that may be outdated or unavailable is utilized to predict what the program will do next. For example, suppose a map application runs two processes that simultaneously require the exact location data. In that case, one will take the information first, preventing the other from using it. The data is viewed as null by the subsequent operation.
Examples of race conditions
A light switch is a basic example of a race condition. Many light switches are linked to single ceiling lights in certain homes. When these circuits are utilized, the switch position is rendered useless. If the light is turned on, moving either switch away from its present position turns it off. Similarly, shifting either switch from its current position turns it on if the light is turned off.
Consider what would happen if two persons tried to turn on the light simultaneously by using two different switches. One command may negate the other, or the two acts may cause the circuit breaker to trigger.
A race condition may arise in computer memory or storage if requests to read and write a significant quantity of data are received almost simultaneously. The software attempts to overwrite all of the old data while that old data is still being read. As a result, one or more of the following may occur:
- The computer crashes or detects an unauthorized software operation error.
- Errors in reading old data as well as generating new data.
Multithreading and parallel processing
The term “parallel programming” refers to a broad topic. It can refer to a variety of operations that are operating on the same or different computers.
Multithreading is the simultaneous execution of more than one sequential set (thread) of instructions.
What happens during a race condition attack?
Many typical cyberattacks have race situations, including web applications, file systems, and networking environments. The excellent thing is that race conditions are relatively uncommon since they rely on attackers manipulating a system’s process in a very short period of time. Most attackers will instead concentrate on simpler types of attacks, such as SQL injection vulnerabilities.
Regardless, race condition attacks can cause significant breaches and provide attackers complete access to protected system’s private data. This type of attack can target various systems, including an access control list (ACL), a payroll or human resources database, a transactional system, a financial ledger, or any other data repository.
The security impact of race conditions
Suppose the software is built to execute tasks in a specified order. In that case, it may encounter security difficulties if requested to do two or more processes simultaneously. A malicious attacker can exploit the time delay between when a service is started and when a security control takes effect to cause a deadlock or thread block condition.
A deadlock vulnerability is a particularly severe type of denial-of-service vulnerability. It can happen when two or more threads in a circular chain must wait for one another to acquire or release a lock. Because such locks can never be obtained or removed if the chain is circular, this circumstance results in a deadlock, bringing the entire software system to a standstill.
Thread blocking can also have a significant influence on application performance. One thread calls a long-running operation while holding a lock and preventing other threads from progressing in this concurrency problem.
How to identify race conditions?
It is difficult to detect and recognize race circumstances. They are semantic issues that can come from a variety of coding problems. It is preferable to create code so that these issues are avoided from the start.
To discover race problems, programmers employ dynamic and static analysis techniques. Static testing software examines a program without running it. They do, however, generate a large number of misleading reports. Although dynamic analysis methods provide fewer erroneous reports, they may miss race situations not implemented directly within the program.
Data race can cause race circumstances when two threads simultaneously target the same memory region, with at least one being a write operation. Data races are simpler to identify than race circumstances since they require certain conditions to arise. Data race detection tools, such as the Go Project’s Data Race Detector, keep an eye out for data race scenarios. Race situations are more tightly related to application semantics and offer more severe issues.
How to prevent race conditions?
There are two techniques for developers to prevent race conditions in software such as web applications, operating systems, and so on:
- Avoid shared states by evaluating code to verify that when shared resources are part of a system or process, atomic operations that operate independently of other processes are in place. Locking is utilized to guarantee the nuclear functioning of essential elements of code. Immutable objects, which cannot be changed once created, can also be used.
- Use thread synchronization in a particular section of the program that can only run one thread at a time.
Race conditions reveal themselves in various ways in software, storage, memory, and networking. Quickly and effectively monitoring and preventing them is an essential component of software and technology design and development.
Preventing race situations is especially critical because hackers may use race-condition vulnerabilities to obtain unauthorized access to networks. Dirty Cow is a well-known race condition-based exploit that uses a weakness in the Linux kernel’s memory subsystem to generate a race situation. The attacker writes privileges for read-only memory mappings.
Race condition vulnerability impact is not high but medium or low. It comes under low-hanging vulnerability.