A simple example is as follows: Consider a Web application that allows a user to edit pages, but allows administrators to lock pages to prevent editing. A user requests to edit a page, getting a form by which they can alter its content. Before the user submits the form, an administrator locks the page, which should prevent editing. However, since the user has already begun editing, when they submit the form, their edits are accepted. When the user began editing, their authorization was checked, and they were indeed allowed to edit. However, the authorization was used later, after they should no longer have been allowed.
In Unix, the following C code, when used in a setuid program, is a TOCTTOU bug:
fd = open(file, O_RDONLY);
// do something with fd...
exit(1);
}
This race condition is vulnerable to an attack:
Although this sequence of events requires precise timing, it is possible for an attacker to arrange such conditions without too much difficulty.
The implication is that the access system call, as it currently exists in Unix, should never be used except as the first step of a Test and Test-and-set.