In software development, time-of-check to time-of-use (TOCTOU, TOCTTOU or TOC/TOU) is a class of software bugs caused by a race condition involving the checking of the state of a part of a system (such as a security credential) and the use of the results of that check.
TOCTOU race conditions are common in Unix between operations on the file system, [1] but can occur in other contexts, including local sockets and improper use of database transactions. In the early 1990s, the mail utility of BSD 4.3 UNIX had an exploitable race condition for temporary files because it used the mktemp()
[2] function. [3] Early versions of OpenSSH had an exploitable race condition for Unix domain sockets. [4] They remain a problem in modern systems; as of 2019, a TOCTOU race condition in Docker allows root access to the filesystem of the host platform. [5] In the 2023 Pwn2Own competition in Vancouver, a team of hackers were able to compromise the gateway in updated Tesla model 3 using this bug. [6]
In Unix, the following C code, when used in a setuid
program, has a TOCTOU bug:
if(access("file",W_OK)!=0){exit(1);}fd=open("file",O_WRONLY);write(fd,buffer,sizeof(buffer));
Here, access is intended to check whether the real user who executed the setuid
program would normally be allowed to write the file (i.e., access
checks the real userid rather than effective userid).
This race condition is vulnerable to an attack:
Victim | Attacker |
---|---|
if(access("file",W_OK)!=0){exit(1);} | |
After the access check, before the open, the attacker replaces file with a symlink to the Unix password file /etc/passwd :symlink("/etc/passwd","file"); | |
fd=open("file",O_WRONLY);write(fd,buffer,sizeof(buffer)); /etc/passwd |
In this example, an attacker can exploit the race condition between the access
and open
to trick the setuid
victim into overwriting an entry in the system password database. TOCTOU races can be used for privilege escalation to get administrative access to a machine.
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 applications cannot assume the state managed by the operating system (in this case the file system namespace) will not change between system calls.
Exploiting a TOCTOU race condition requires precise timing to ensure that the attacker's operations interleave properly with the victim's. In the example above, the attacker must execute the symlink
system call precisely between the access
and open
. For the most general attack, the attacker must be scheduled for execution after each operation by the victim, also known as "single-stepping" the victim.
In the case of BSD 4.3 mail utility and mktemp()
, [2] the attacker can simply keep launching mail utility in one process, and keep guessing the temporary file names and keep making symlinks in another process. The attack can usually succeed in less than one minute.
Techniques for single-stepping a victim program include file system mazes [7] and algorithmic complexity attacks. [8] In both cases, the attacker manipulates the OS state to control scheduling of the victim.
File system mazes force the victim to read a directory entry that is not in the OS cache, and the OS puts the victim to sleep while it is reading the directory from disk. Algorithmic complexity attacks force the victim to spend its entire scheduling quantum inside a single system call traversing the kernel's hash table of cached file names. The attacker creates a very large number of files with names that hash to the same value as the file the victim will look up.
Despite conceptual simplicity, TOCTOU race conditions are difficult to avoid and eliminate. One general technique is to use error handling instead of pre-checking, under the philosophy of EAFP – "It is easier to ask for forgiveness than permission" rather than LBYL – "look before you leap" – in this case there is no check, and failure of assumptions to hold are signaled by an error being returned. [9]
In the context of file system TOCTOU race conditions, the fundamental challenge is ensuring that the file system cannot be changed between two system calls. In 2004, an impossibility result was published, showing that there was no portable, deterministic technique for avoiding TOCTOU race conditions when using the UNIX access
and open
filesystem calls. [10]
Since this impossibility result, libraries for tracking file descriptors and ensuring correctness have been proposed by researchers. [11]
An alternative solution proposed in the research community is for UNIX systems to adopt transactions in the file system or the OS kernel. Transactions provide a concurrency control abstraction for the OS, and can be used to prevent TOCTOU races. While no production UNIX kernel has yet adopted transactions, proof-of-concept research prototypes have been developed for Linux, including the Valor file system [12] and the TxOS kernel. [13] Microsoft Windows has added transactions to its NTFS file system, [14] but Microsoft discourages their use, and has indicated that they may be removed in a future version of Windows. [15]
File locking is a common technique for preventing race conditions for a single file, but it does not extend to the file system namespace and other metadata, nor does locking work well with networked filesystems, and cannot prevent TOCTOU race conditions.
For setuid
binaries, a possible solution is to use the seteuid()
system call to change the effective user and then perform the open()
call. Differences in setuid()
between operating systems can be problematic. [16]
In programming and information security, a buffer overflow or buffer overrun is an anomaly whereby a program writes data to a buffer beyond the buffer's allocated memory, overwriting adjacent memory locations.
Mach is a kernel developed at Carnegie Mellon University by Richard Rashid and Avie Tevanian to support operating system research, primarily distributed and parallel computing. Mach is often considered one of the earliest examples of a microkernel. However, not all versions of Mach are microkernels. Mach's derivatives are the basis of the operating system kernel in GNU Hurd and of Apple's XNU kernel used in macOS, iOS, iPadOS, tvOS, and watchOS.
Network File System (NFS) is a distributed file system protocol originally developed by Sun Microsystems (Sun) in 1984, allowing a user on a client computer to access files over a computer network much like local storage is accessed. NFS, like many other protocols, builds on the Open Network Computing Remote Procedure Call system. NFS is an open IETF standard defined in a Request for Comments (RFC), allowing anyone to implement the protocol.
In computer security, an access-control list (ACL) is a list of permissions associated with a system resource. An ACL specifies which users or system processes are granted access to resources, as well as what operations are allowed on given resources. Each entry in a typical ACL specifies a subject and an operation. For instance,
In computing, a symbolic link is a file whose purpose is to point to a file or directory by specifying a path thereto.
A virtual file system (VFS) or virtual filesystem switch is an abstract layer on top of a more concrete file system. The purpose of a VFS is to allow client applications to access different types of concrete file systems in a uniform way. A VFS can, for example, be used to access local and network storage devices transparently without the client application noticing the difference. It can be used to bridge the differences in Windows, classic Mac OS/macOS and Unix filesystems, so that applications can access files on local file systems of those types without having to know what type of file system they are accessing.
The inode is a data structure in a Unix-style file system that describes a file-system object such as a file or a directory. Each inode stores the attributes and disk block locations of the object's data. File-system object attributes may include metadata, as well as owner and permission data.
chroot
is an operation on Unix and Unix-like operating systems that changes the apparent root directory for the current running process and its children. A program that is run in such a modified environment cannot name files outside the designated directory tree. The term "chroot" may refer to the chroot(2) system call or the chroot(8) wrapper program. The modified environment is called a chroot jail.
Privilege escalation is the act of exploiting a bug, a design flaw, or a configuration oversight in an operating system or software application to gain elevated access to resources that are normally protected from an application or user. The result is that an application or user with more privileges than intended by the application developer or system administrator can perform unauthorized actions.
In computing, a file system or filesystem governs file organization and access. A local file system is a capability of an operating system that services the applications running on the same computer. A distributed file system is a protocol that provides file access between networked computers.
Theodore Yue Tak Ts'o is an American software engineer mainly known for his contributions to the Linux kernel, in particular his contributions to file systems. He is the secondary developer and maintainer of e2fsprogs, the userspace utilities for the ext2, ext3, and ext4 filesystems, and is a maintainer for the ext4 file system.
Most file systems include attributes of files and directories that control the ability of users to read, change, navigate, and execute the contents of the file system. In some cases, menu options or functions may be made visible or hidden depending on a user's permission level; this kind of user interface is referred to as permission-driven.
File locking is a mechanism that restricts access to a computer file, or to a region of a file, by allowing only one user or process to modify or delete it at a specific time and to prevent reading of the file while it's being modified or deleted.
The proc filesystem (procfs) is a special filesystem in Unix-like operating systems that presents information about processes and other system information in a hierarchical file-like structure, providing a more convenient and standardized method for dynamically accessing process data held in the kernel than traditional tracing methods or direct access to kernel memory. Typically, it is mapped to a mount point named /proc at boot time. The proc file system acts as an interface to internal data structures about running processes in the kernel. In Linux, it can also be used to obtain information about the kernel and to change certain kernel parameters at runtime (sysctl).
A file system API is an application programming interface through which a utility or user program requests services of a file system. An operating system may provide abstractions for accessing different file systems transparently.
The OpenBSD operating system focuses on security and the development of security features. According to author Michael W. Lucas, OpenBSD "is widely regarded as the most secure operating system available anywhere, under any licensing terms."
The following tables compare general and technical information for a number of file systems.
An NTFS reparse point is a type of NTFS file system object. It is available with the NTFS v3.0 found in Windows 2000 or later versions. Reparse points provide a way to extend the NTFS filesystem. A reparse point contains a reparse tag and data that are interpreted by a filesystem filter driver identified by the tag. Microsoft includes several default tags including NTFS symbolic links, directory junction points, volume mount points and Unix domain sockets. Also, reparse points are used as placeholders for files moved by Windows 2000's Remote Storage Hierarchical Storage System. They also can act as hard links, but are not limited to pointing to files on the same volume: they can point to directories on any local volume. The feature is inherited to ReFS.
Tiger is a security software for Unix-like computer operating systems. It can be used both as a security audit tool and a host-based intrusion detection system and supports multiple UNIX platforms. Tiger is free under the GPL license and unlike other tools, it needs only of POSIX tools, and is written entirely in shell language.
The NetBSD rump kernel is the first implementation of the "anykernel" concept where drivers either can be compiled into or run in the monolithic kernel or in user space on top of a light-weight kernel. The NetBSD drivers can be used on top of the rump kernel on a wide range of POSIX operating systems, such as the Hurd, Linux, NetBSD, DragonFly BSD, Solaris kernels and even Cygwin, along with the file system utilities built with the rump libraries. The rump kernels can also run without POSIX directly on top of the Xen hypervisor, an L4 microkernel using the Genode OS Framework or even on "OS-less" bare metal.
{{cite journal}}
: CS1 maint: date and year (link){{cite book}}
: CS1 maint: location missing publisher (link){{cite journal}}
: CS1 maint: date and year (link){{cite web}}
: CS1 maint: date and year (link){{cite web}}
: CS1 maint: date and year (link)