Jay Bosamiya Software Security Researcher

Race Conditions & Exploiting Them

Influenced by this amazing live stream by Gynvael Coldwind, where he explains about race conditions

If a memory region (or file or any other resource) is accessed twice with the assumption that it would remain same, but due to switching of threads, we are able to change the value, we have a race condition.

Most common kind is a TOCTTOU (Time-of-check to Time-of-use), where a variable (or file or any other resource) is first checked for some value, and if a certain condition for it passes, then it is used. In this case, we can attack it by continuously "spamming" this check in one thread, and in another thread, continuously "flipping" it so that due to randomness, we might be able to get a flip in the middle of the "window-of-opportunity" which is the (short) timeframe between the check and the use.

Usually the window-of-opportunity might be very small. We can use multiple tricks in order to increase this window of opportunity by a factor of 3x or even up to ~100x. We do this by controlling how the value is being cached, or paged. If a value (let's say a long int) is not aligned to a cache line, then 2 cache lines might need to be accessed and this causes a delay for the same instruction to execute. Alternatively, breaking alignment on a page, (i.e., placing it across a page boundary) can cause a much larger time to access. This might give us higher chance of the race condition being triggered.

Smarter ways exist to improve this race condition situation (such as clearing TLB etc, but these might not even be necessary sometimes).

Race conditions can be used, in (possibly) their extreme case, to get ring0 code execution (which is "higher than root", since it is kernel mode execution).

It is possible to find race conditions "automatically" by building tools/plugins on top of architecture emulators. For further details, http://vexillium.org/pub/005.html