sudo and OpenDoas timestamp files (2020)
A 2020 write-up demonstrates reusing sudo timestamp files across SSH sessions for passwordless sudo, fixed via session-leader start times.
The author contrasts OpenBSD doas(1)'s persist feature, which uses TIOCSETVERAUTH/TIOCCHKVERAUTH/TIOCCLRVERAUTH ioctls to track authenticated TTYs with timeouts, with sudo(8)'s timestamp files bound to PPID or TTY number. A proof-of-concept reused a sudo timestamp file after an SSH session ended by opening a newly recycled pseudo-tty and calling clone(2) in a loop until matching the sshd subprocess's PPID, then ran sudo without a password. The proposed mitigation binds timestamps to the session leader's monotonic start time; this was implemented in OpenDoas and proposed upstream. sudo(8) 1.8.22 (2017) already added the equivalent session start-time check (commit 1709dc7f77).
- doas persist uses TTY ioctls (TIOCSETVERAUTH, TIOCCHKVERAUTH, TIOCCLRVERAUTH); sudo relies on timestamp files tied to PPID or TTY.
- PoC reuses a sudo timestamp file by claiming a recycled pseudo-tty and cloning until the PPID matches sshd's subprocess.
- Proposed fix: validate the session leader's monotonic start time, implemented in OpenDoas.
- sudo 1.8.22 (2017) added equivalent process start-time checks across all supported operating systems.
Full article385 words · extracted from xn--1xa.duncano.de · click to collapse
The persist feature in OpenBSDs doas(1) uses a new
tty(4) ioctl(2)
which allows to create (TIOCSETVERAUTH), clear (TIOCCLRVERAUTH) and check
(IOCCHKVERAUTH) authentications to the specific TTY with a timeout.
sudo(8) uses timestamp files to avoid having to enter the password repeatedly,
they are bound to the PPID
(Parent process identifier) or TTY number.
After investigating how sudo(8) does it and reading old vulnerabilities in sudo(8),
I was a bit concerned about implementing it, but the quality of life improvements
of not having to enter the password on each command is really nice to have I decided to
implement timestamp files similarly to sudo(8) and avoid all the previous issues sudo(8)
had with it.
One issue I had with timestamp files in sudo(8) was that they were fairly easy to be reuse
on linux, as a PoC (proof of concept) I authenticated my self in a ssh session and used sudo(8),
which created a timestamp file for the specific pseudo tty and the PPID.
Then my PoC would open a new pseudo tty and would be assigned to the one that was free after
the ssh session was closed.
To match the PPID, I just called clone(2) in a loop until I got the previous PPID of the sshd
sub-process.
This then allowed me to reuse the timestamp file from the ssh session and execute sudo(8) from
the PoC without having to enter a password.
When I was thinking about how this could be fixed my Idea was to use the start time, of the TTYs session leader, the start time is a monotonic clock that can only go forwards from the time of boot.
There is no way to get the same TTY/PPID with the same start time of the session leader, other than rebooting the system, but there are other measures to avoid that.
I implemented this in OpenDoas and suggested the sudo(8) maintainers to implement the same
mechanism to avoid this kind of “attack”. Within a few hours it landed in sudo(8) and
every supported operating system sudo(8) supports, has the capability to receive the
start time of a process so this new feature is not only limited to linux.
This new feature was added released sudo(8) 1.8.22 in 2017.