sudo: digest race condition
In late 2015, I was discussing difficult-to-understand manpages on IRC, and the topic wandered (perhaps inevitably) to the sudoers manpage, which a xkcd strip claimed to be the “most ridiculous offender of all”.
We noticed that there’d been a new feature added recently: you could add a digest (e.g., SHA-2) of a binary, and sudo would only execute the binary if it matched the digest. Neat! It even provided an example of how this could be used:
“This may be useful in situations where the user invoking sudo has write access to the command or its parent directory.”
Of course, I immediately asked “what is the chance that it has a race condition?” (a case of vulnerability discovery by simply reading the manpage..) and upon checking the source, things quickly fell apart..
At the time, the sudo code opened the binary, checksummed the contents, closed it, and then later called execve to execute it; this is a pretty typical TOCTOU (time of check to time of use) bug, since you can just replace the binary in the time between the check and the execution. (In fact, you might get quite a long time to do this, because sudo prompts for your password after checksumming the binary but before executing it.)
Todd Miller (the current sudo maintainer) responded extremely quickly to my report, fixing the documentation to warn about the race condition, and later partially mitigating the issue by using fexecve. fexecve uses a file descriptor rather than a path to a binary, which allows sudo to checksum the binary and then be sure that the same binary is executed, rather than a different one substituted by an attacker. Obviously, if they have write access to the binary itself, then they can simply modify it after the check; further mitigation (such as copying the binary elsewhere) is almost certainly more trouble than it’s worth.
You can find my original disclosure on oss-security; it was assigned CVE-2015-8239.