Download presentation
Presentation is loading. Please wait.
Published byReynold O’Brien’ Modified over 8 years ago
1
Race conditions and synchronization issues Exploiting UNIX
2
access(2) system call SUID programs run with privileges equal to the program owner (typically root or some privileged user) instead of caller More specifically, SUID have effective ID equal to the owner, while real ID equal to caller SUID programs, when accessing files, may need to decide if the caller has privileges to the file It cannot rely on the basic UNIX mechanism for enforcing file permissions, as the privileges of the program’s owner are higher than that of the caller The access(2) system call was introduced to address this issue Signature: int access(const char* path, int mode)
3
Real ID vs. Effective ID access(2) determines privileges based on the real ID of the process. The mode can be any combination or read, write, execute, or existential test. It returns 0 (if success) or -1 in these events: [ENOTDIR]A component of the path prefix is not a directory. [ENAMETOOLONG]A component of a pathname exceeded {NAME_MAX} characters, or an entire path name exceeded {PATH_MAX} characters. [ENOENT]The named file does not exist. [ELOOP]Too many symbolic links were encountered in translating the pathname. [EROFS]Write access is requested for a file on a read-only file system. [ETXTBSY]Write access is requested for a pure procedure (shared text) file presently being executed. [EACCES]Permission bits of the file mode do not permit the requested access, or search permission is denied on a component of the path prefix. [EFAULT]Path points outside the process's allocated address space. [EIO]An I/O error occurred while reading from or writing to the file system. [EINVAL]An invalid value was specified for mode.
4
Using access(2) In usage, a call is made to access(2) to check the caller’s privileges, and if it returns 0, a subsequent call to a file system operation such as open(2) is performed. Even if tightly coupled, the two operations are never atomic. In particular, both system calls take as inputs a path name, and must evaluate it in terms of a handle to a file As a result, it is proper to say that access(2) determines privileges with respect to a “snapshot” of the file system, while the subsequent call accesses a (possibly different) snapshot. Attackers can exploit this short time span to make improper changes to the file system. These changes will succeed because UNIX does not enforce write locks (e.g., modifications of the file system structure). Such enforcement is a necessary condition for security of the combined transaction.
5
A TOCTTOU attack
6
Proposed solution (fork) Dean and HU propose two portable solutions for the access(2) TOCTTOU vulnerability: Avoid access(2) altogether. If the SUID program needs to open a file that should be checked against caller’s privileges, do: 1. fork a new child process 2. use setuid(2) system call to set the effective ID of child process equal to the caller (real ID) of parent process 3. Let the forked process obtain a file descriptor 4. Use standard UNIX IPC to pass the descriptor to parent This solution enforces consistency, so it is secure. However, it is also slow.
7
Proposed solution (k-race)
8
Strategy of k-race Force the attacker to win multiple races Each call to access must be preceded by a switch of the symbolic link to some public file, while each call to open must resolve to the same file (attacker’s intended target) Additionally, after the first race, requests for file descriptors access the cache, which being very fast, results in attackers always losing the race.
9
New attack Circumvent caching by creating many symbolic links, without re-using a link in any following race Force victim to sleep on I/O, giving attacker execution time between races in which to modify symlinks Dramatically increase the probability of success by: Using a symlink maze to dramatically increase the probability that the victim will sleep in each race Use atime system call (which says when a directory has been traversed last) to predict when it is safe to change an intermediate symlink to point to system file
10
I/O delays Instead of dir0, use dir/dir/…/dir/lnk Victim will sleep if at least one directory in the path is not in cache Use chains of MAXPATHLEN (typically 1024-4096 characters) and use links to connect many chains in a maze (up to max symlinks supported in path) Victim must traverse C*N directories to resolve a name, where C is the number of symlinks and N the depth of each chain In Linux, attack may be able to force traversal of 80,000 directories!
11
Increasing probability of success The attacker polls the directory structure to find out when the system updates access time on one of the symbolic links in the maze At that point, it is safe to switch that symlink to point to the system file resource. Experimental results: Success probability between 19% to 100% on k=100. Even randomizing when to make calls to access(2) or open(2) results in reasonable attack success probabilities K=100 already slower than fork-based solution
12
Conclusion Needed: Standardization of UNIX kernel capabilities to either: support temporary privilege drop support an O_RUID flag that makes system calls fail or succeed based on the real ID of the process Note: UNIX flavors often support better mechanisms than access(2), and therefore this call is in disuse However, code that uses such infrastructures is not portable
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.