Race Conditions Exploitation Case Study
Race condition vulnerabilities exist if an application uses multiple threads or processes to perform actions in parallel in an unsafe fashion. If this occurs within an application, a number of different results can occur from simple functionality issues to major security vulnerabilities.
The Meltdown vulnerability is an example of a high-impact race condition vulnerability. This vulnerability allows an attacker to read data from privileged memory addresses on a computer.
The Meltdown race condition
The Meltdown vulnerability arises from how certain computers handle access to restricted memory. Due to an optimization in the code, a race condition existed between two crucial components:
- Permissions check: Before providing access to a memory address, the request is verified to ensure that the requesting application has the rights to access that memory address. If not, the access attempt is rejected.
- Data access and caching: If the data stored at a particular memory address is not currently stored in the cache, it is moved to the cache as part of the access operation. This makes it quicker and easier to access this memory in the near future.
In theory, these two operations should be performed sequentially, only performing the access attempt if the application has the right to access the data. The Meltdown vulnerability exists because of an optimization in this process where the permissions check and access and caching are performed in parallel. However, the system is designed to ensure that access to the data is not provided to the application until the permissions check is complete (even if the caching occurred first).
Exploiting the Meltdown vulnerability requires an attacker to take advantage of this race condition. This is accomplished via the following steps where BASE is a value selected by the attacker and PRIVILEGED_VALUE is the value stored at a restricted memory address:
- The attacker requests the data at a memory location of BASE+PRIVILEGED_VALUE.
- The computer simultaneously moves the desired memory to the cache and checks if the attacker should have been able to perform the calculation to get the desired address.
- The initial request is denied.
- The attacker attempts to access memory locations in the range BASE+POSSIBLE_VALUES.
- The attacker records the time taken to access each of these values.
The result of this attack is that the value of PRIVILEGED_VALUE will be revealed with high probability. This is because the Meltdown race condition means that — in parallel with the permissions check — this value will be extracted and used in the calculation BASE+PRIVILEGED_VALUE, and the resulting memory location will be accessed and the data that it is contained is moved to the cache.
This means that, when the attacker attempts to access the range of potential memory addresses, one should be accessed much more quickly than the others. This is because the address BASE+PRIVILEGED_VALUE has been recently accessed and cached, while the others (hopefully) have not been. This makes it possible for the attacker to derive the value of PRIVILEGED_VALUE by identifying the cached memory address and subtracting off the value of BASE.
The impact of Meltdown
Meltdown was a dangerous vulnerability because it allowed an attacker to gain access to the data stored at any memory location, both privileged and unprivileged. Computers store a great deal of sensitive information (passwords, SSH keys and so on), and the Meltdown vulnerability could be used to read out all of a computer’s privileged memory.
Meltdown demonstrated the potential risk of optimizations within an application. Meltdown’s race condition existed because of a desire to speed memory access rather than following the safer path of actually verifying permissions before attempting access to privileged memory locations.
- Meltdown and Spectre, meltdownattack.com
- Spectre and Meltdown explained: A comprehensive guide for professionals, TechRepublic
- Race Condition, TechTerms