Security Laboratory

Security Laboratory

Security Laboratory: Methods of Attack Series

These papers introduce you to the most common attack methods against computer systems and networks and the basic strategies used to mitigate those threats.

Other Related Articles in Security Laboratory: Methods of Attack Series

Race Conditions

By Stephen Northcutt

"A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence in order to be done correctly."[1] Race conditions exploit that small window of time between when a security control is applied and when the service is used. Usually these are very tricky and relatively difficult to pull off.

Race condition problems can be notionally divided into two categories:
  • Interference caused by untrusted processes. Some security taxonomies call this problem a "sequence'' or "non-atomic'' condition. These are conditions caused by processes running other different programs, which ``slip in'' other actions between steps of the secure program. These other programs might be invoked by an attacker specifically to cause the problem.
  • Interference caused by trusted processes (from the secure program's point of view). Some taxonomies call these deadlock, livelock, or locking failure conditions. These are conditions caused by processes running the "same'' program. Since these different processes may have the "same'' privileges, if not properly controlled, they may be able to interfere with each other in a way other programs can't. Sometimes this kind of interference can be exploited.[2]

Race conditions are also sometimes known as Time of Check/Time of Use or TOC/TOU attacks and this is a good choice of terminology. You are going to do some checks when you create or open a file, but what if your program doesn't use the file right then. Maybe you just want to do all your "housekeeping" in one function and then use the file handle later to write to the file. What if something changes? Programs that watch for events and then sleep() are particularly dangerous. In general, the greater the difference in time between the time of checking and the time of use, the more exposure to a race condition. There is an illustration of this on Sun's Java web site[3].

An example of a race condition

To understand why, think of a common example such as a script that rebuilds access control lists from a database each night to control who gets to access the payroll system. Updating the ACLs nightly is a laudable goal. It keeps the access list up-to-date, removing employees who no longer need access to the data and adding new ones who suddenly do. The list never gets stale because it is completely rewritten each night from scratch. Paradoxically, this actually can cause a problem if the designer of the system is not careful.

One way to update the list would be to remove the existing ACL, then go through all the entries in the employee database to find out who has the special payroll access flag on their account. Those who do are added to the list. Once the list is completed, a new ACL is written.

You may have just spotted an obvious point of concern. "What happens between the time the ACL is removed and the time the database search is finished as the new ACL is created?" That payroll system is probably wide open for anyone to use. If your employee database is large and takes some time to search, the window of opportunity for an attack could be as much as several seconds, or even a minute or more. That is plenty of time for an attacker to make queries while the database is temporarily unprotected.

A slightly more elaborate scheme could be to hold off deleting the old ACL until the new one is ready to be committed; but even so, this may involve a short window of opportunity for malicious use. Even a half a second could be enough if the attacker can guess when that half second will occur. Race conditions are sometimes quite subtle and appear in the oddest places. Careful programming and good administration practices usually can clear them up, but you've got to find them first.

Questions managers or auditors can ask programmers for software security related to race conditions?

  • Do you use signals? (Ask them to grep source code for "signal.h".) Signals are exploitable because they introduce Time of Check/Time of Use. Owasp[4] as well as CERT secure code[5] have a write up on this.
  • Are there cases where you check access with access(2) then open(2) is clearly non-atomic? Users can move files in between the two calls (Time of Check/Time of Use).[6]
NOTE: The Apple developer site[7], while a bit technical for management types, is loaded with information on race conditions, functions to avoid (fopen, chmod, chown, stat, mktemp), and the safe functions to use instead.