I was reading: https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use
They showed this code to be buggy and I totally understand why it’s so:
if (access("file", W_OK) != 0) { exit(1); } // Attacker: symlink("/etc/passwd", "file"); fd = open("file", O_WRONLY); // Actually writing over /etc/passwd write(fd, buffer, sizeof(buffer));
But the real question is how to protect against this type of exploits?
Advertisement
Answer
You can use the O_NOFOLLOW
flag. It will cause the open
to fail if basename
of the path is a symbolic link. That would solve the described attack.
To cover links along the directory path, you can check whether frealpath(fd, ...)
matches what you would expect.
Another way to prevent a process from overwriting /etc/passwd
is to run it as non-root so that it won’t have permission. Or, you can use chroot – or more generally, a container – to prevent the host system’s /etc/passwd
being visible to the process.
More generally though, filesystem TOCTOU is unsolvable at the moment on Linux. You would need transaction support either on filesystem or system call level – which are lacking.