About | ACP | Buy | Industry Watch | Learning Curve | Search | Test Drive
Home » Learning Curve

Sudos & Sudon'ts

Systems can offer security; it's up to you to take advantage of it.

Get It

Try It

A system only needs security if it either is or has something to protect. As security cannot be built into a system after the fact - vis Microsoft's dilemma with Windows - a good system has to have proper security at the user's disposal.

A good system must foremost protect itself without waiting for a nod from its user. If the system goes down no one benefits. It must be assumed the system will stand.

A good system must also offer adequate means for a user to protect personal data.

Somewhere between the one and the other the user at times will assume the role of the system itself. But as this role is coveted by black hats and as errors committed when in this role can have dire consequences it's necessary to think first before leaping.

But back to basics first.

It's All Files

Everything on Unix is a file. Directories are files just like ordinary files. Other arcane objects such as sockets and symbolic links are just files too.

Every file belongs to a user and a group and every file - and directory - has read write and execute permissions for its user, group, and the others.

For a program file or a script to run it must have the execute bit set for the appropriate field - user, group, or other. What read and write mean in this context is obvious.

For directories it's a bit different: if a read bit is set for you (as user, group, or other) you'll be able to read it - list its contents. And if its execute bit is set you'll be able to physically 'enter' it - change directory into it.

If its write bit is set then you'll be able to modify it.

Directories contain lists of file names and corresponding inodes. An inode is an index into an ilist (volume control block) with all information about a file.

Being able to modify a directory means being able to write to it - to remove, add, or change file names or their inodes. If you can't write to a directory you can't add files, remove them, rename them, or anything.

[Protecting files is of course another matter: simply because a directory is write protected doesn't mean its files also are.]

Root & Sudo

Unix is a multiuser system. Every Unix user has an account. And one account on Unix can do and get at almost anything.


root isn't the name of the 'root' account; the 'root' account can have any name and 'root' is most common; but by definition any account with a user ID of 0 (zero) and a group ID of 0 (zero) is a 'root account'. Thus it is possible to have any number of root accounts on a system, or to redefine 'root' as a low privilege account and rename the old root account 'foo'. And so forth.

% cat /etc/passwd | grep 0:0
root:*:0:0:System Administrator:/var/root:/bin/tcsh

The second field in the above is for the password for the root account; the encrypted password is supposedly an asterisk ('*'). But Unix uses DES encryption and no password regardless of length is reduced to a single character with DES. The root account on the above system is therefore effectively disabled.

There's a reason for this: the recurring 'shoot oneself in the foot' syndrome coupled with the threat of having your system compromised: any program a user runs will normally have the access rights of that user - and that includes rogue programs.

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these two things:

        #1) Respect the privacy of others.
        #2) Think before you type.

Running the root account - even from the command line - is dangerous; running GUI apps as root is even more so.

So some distros such as OS X and Ubuntu have the root account disabled 'out of the box' in the above way. Yet root access is sometimes necessary; there must therefore be some way of getting root access even if the root account is disabled.

That way is often sudo. sudo is a program residing commonly in /usr/bin.

% ls -ailno /usr/bin/sudo
24466 ---s--x--x  1 0  0  - 96384 Aug  7  2005 /usr/bin/sudo

The zeros in the above denote the user and group of the file; /usr/bin/sudo belongs to user 0 and group 0.

The string '---s--x--x' is a representation of the access rights for the file. Dashes represent 'no attribute'. The first dash can be replaced by a 'd' to denote a directory; the next two dashes are for read and write access respectively for the user (owner) of the file. The 's' in the next position represents a so called 'set UID' bit. This bit assumes execute rights but adds something to the mix. The remaining four dashes denote no read or write access respectively for either the group the file belongs to or for anyone else.

/usr/bin/sudo may be run by anyone but not even root can read it or modify it. And then of course there's that 's' bit.

The set UID bit.

The set UID bit is a way to change the effective user of a program. sudo has the bit set and it's owned by root; anyone is allowed to run sudo; therefore anyone running sudo is effectively running it as root.

sudo may therefore be described as a privilege escalation trampoline: you hop on as yourself and bounce off as root.

But that's where the code in sudo comes in: it performs a number of authentication checks before it lets you bounce back off again. But if you pass all the tests your command will effectively run as root and not as you.

Sudo Syntax

sudo doesn't just escalate you to root: it 'substitutes a user' - which by default as with its earlier counterpart su is root.

       sudo -V | -h | -l | -L | -v | -k | -K | -s | [ -H ] [-P ]
       [-S ] [ -b ] | [ -p prompt ] [ -c class|- ] [ -a auth_type]
       [ -u username|#uid ] command

Anyone can invoke sudo but only after passing the authentication checks will sudo run the command it's given. By default on OS X a user must be a member of the admin group and be able to supply the user's password. [This can be changed.]

sudo determines who can do what by consulting the protected file /etc/sudoers.

% ls -ailo /etc/sudoers
24465 -r--r-----  1 root  wheel  - 341 Jul 14  2004 /etc/sudoers

% sudo cat /etc/sudoers
# sudoers file.
# This file MUST be edited with the 'visudo' command as root.
# See the sudoers man page for the details on how to write a sudoers file.

# Host alias specification

# User alias specification

# Cmnd alias specification

# Defaults specification

# User privilege specification
root    ALL=(ALL) ALL
%admin  ALL=(ALL) ALL

Following is a brief explanation of sudo syntax.

--  Stop processing command line arguments.
-a  Set the authentication type.
-b  Run the given command in the background.
-c  Limit resources by the given login class.
-H  Set the $HOME environment variable for the target user.
-h  Print usage message and exit.
-K  Remove the user's time stamp entirely.
-k  Invalidate the user's time stamp.
-L  List parameters that may be set on a 'Defaults' line in /etc/sudoers.
-l  List allowed and forbidden commands for the current user.
-P  Preserve the user's group vector.
-p  Override the default password prompt.
-S  Read the password from stdin rather than a terminal device.
-s  Run the specified shell. [Default as given in /etc/passwd.]
-u  Run the command as the specified user. [Default root.]
-V  Print version number and exit.
-v  Update the user's time stamp.

Following is a list of /etc/sudoers defaults.

% sudo -L
Available options in a sudoers ``Defaults'' line:

always_set_home: Always set $HOME to the target user's home directory
authenticate: Require users to authenticate by default
badpass_message: Incorrect password message
editor: Path to the editor for use by visudo
env_check: Environment variables to check for sanity
env_delete: Environment variables to remove
env_editor: Visudo will honor the EDITOR environment variable
env_keep: Environment variables to preserve
env_reset: Reset the environment to a default set of variables
exempt_group: Users in this group are exempt from password and PATH requirements
fqdn: Require fully-qualified hostnames in the sudoers file
ignore_dot: Ignore '.' in $PATH
insults: Insult the user when they enter an incorrect password
lecture: Lecture user the first time they run sudo
listpw: When to require a password for 'list' pseudocommand
log_host: Log the hostname in the (non-syslog) log file
log_year: Log the year in the (non-syslog) log file
logfile: Path to log file
loglinelen: Length at which to wrap log file lines (0 for no wrap)
long_otp_prompt: Put OTP prompt on its own line
mail_always: Always send mail when sudo is run
mail_badpass: Send mail if user authentication fails
mail_no_host: Send mail if the user is not in sudoers for this host
mail_no_perms: Send mail if the user is not allowed to run a command
mail_no_user: Send mail if the user is not in sudoers
mailerflags: Flags for mail program
mailerpath: Path to mail program
mailsub: Subject line for mail messages
mailto: Address to send mail to
passprompt: Default password prompt
passwd_timeout: Password prompt timeout
passwd_tries: Number of tries to enter a password
path_info: Allow some information gathering to give useful error messages
preserve_groups: Don't initialize the group vector to that of the target user
requiretty: Only allow the user to run sudo if they have a tty
root_sudo: Root may run sudo
rootpw: Prompt for root's password, not the users's
runas_default: Default user to run commands as
runaspw: Prompt for the runas_default user's password, not the users's
set_home: Set $HOME to the target user when starting a shell with -s
set_logname: Set the LOGNAME and USER environment variables
shell_noargs: If sudo is invoked with no arguments, start a shell
stay_setuid: Only set the effective uid to the target user, not the real uid
syslog: Syslog facility if syslog is being used for logging
syslog_badpri: Syslog priority to use when user authenticates unsuccessfully
syslog_goodpri: Syslog priority to use when user authenticates successfully
targetpw: Prompt for the target user's password, not the users's
timestamp_timeout: Authentication timestamp timeout
timestampdir: Path to authentication timestamp dir
tty_tickets: Use a separate timestamp for each user/tty combo
umask: Umask to use or 0777 to use user's
use_loginclass: Apply defaults in the target user's login class if there is one
verifypw: When to require a password for 'verify' pseudocommand

sudo also does quite a lot to protect you - from threats you probably didn't even consider.

sudo tries to be safe when executing external commands. Variables that control how dynamic loading and binding is done can be used to subvert the program that sudo runs.

To combat this the LD_*, _RLD_*, SHLIB_PATH (HP-UX only), and LIBPATH (AIX only) environment variables are removed from the environment passed on to all commands executed. sudo will also remove the IFS, ENV, BASH_ENV, KRB_CONF, KRBCONFDIR, KRBTKFILE, KRB5_CONFIG, LOCALDOMAIN, RES_OPTIONS, HOSTALIASES, NLSPATH, PATH_LOCALE, TERMINFO, TERMINFO_DIRS and TERMPATH variables as they too can pose a threat.

If the TERMCAP variable is set and is a path name, it too is ignored. Additionally, if the LC_* or LANGUAGE variables contain the / or % characters, they are ignored.

If sudo has been compiled with SecurID support, the VAR_ACE, USR_ACE and DLC_ACE variables are cleared as well. The list of environment variables that sudo clears is contained in the output of sudo -V when run as root.

$ sudo sudo -V
Sudo version 1.6.8p12

Authentication methods: 'pam'
Syslog facility if syslog is being used for logging: local2
Syslog priority to use when user authenticates successfully: notice
Syslog priority to use when user authenticates unsuccessfully: alert
Send mail if the user is not in sudoers
Lecture user the first time they run sudo
Require users to authenticate by default
Root may run sudo
Allow some information gathering to give useful error messages
Visudo will honor the EDITOR environment variable
Set the LOGNAME and USER environment variables
Length at which to wrap log file lines (0 for no wrap): 80
Authentication timestamp timeout: 5 minutes
Password prompt timeout: 0 minutes
Number of tries to enter a password: 3
Umask to use or 0777 to use user's: 022
Path to mail program: /usr/sbin/sendmail
Flags for mail program: -t
Address to send mail to: root
Subject line for mail messages: *** SECURITY information for %h ***
Incorrect password message: Sorry, try again.
Path to authentication timestamp dir: /var/db/sudo
Default password prompt: Password:
Default user to run commands as: root
Path to the editor for use by visudo: /usr/bin/vi
When to require a password for 'list' pseudocommand: any
When to require a password for 'verify' pseudocommand: all
Environment variables to check for sanity:
Environment variables to remove:
Local IP address and netmask pairs:

Note that there is one thing sudo will not ignore.

To prevent command spoofing sudo checks '.' and '' (both denoting the current working directory) last when searching for a command in $PATH. The actual $PATH variable is not modified and is passed unchanged to the program that sudo executes.

[For more on $PATH see below.]

The Four Bins

Unix programs are traditionally found in four locations. There are four locations because originally there was only one and as time went on each successive location accumulated too many files.

The first location for Unix programs was /bin right under root. This was always part of the first (default) mountable file system: it had to be present when the system started up. And as /bin grew a new location was created for less critical files: /usr/bin was commonly mounted on a separate physical device.

[/usr was where all user accounts originally were located - eg /usr/bwk, /usr/dmr, /usr/ken. /usr/bin was therefore regarded informally as a repository for 'user' programs rather than system programs.]

After a while two new locations came about: /sbin and /usr/sbin. [Think of them if you will as repositories for system commands but there's no thorough distinction.]

What's important about these four bins is that they're locked down tight - they're 'hermetically sealed'. And this is important for you and your security.

Hermetically Sealed

The four 'bin' locations should be 'hermetically sealed': the files themselves are owned by root (or in rare cases by another almost equally inaccessible account) and their directories are owned by root as well. And no one else is allowed to modify their contents.

% ls -adilno /bin /sbin /usr/bin /usr/sbin
6757 drwxr-xr-x   35 0  0  -  1190 May 20  2005 /bin
6890 drwxr-xr-x   60 0  0  -  2040 Aug 12  2005 /sbin
6954 drwxr-xr-x  548 0  0  - 18632 Jan 24 20:06 /usr/bin
7083 drwxr-xr-x  171 0  0  -  5814 Jan 24 00:30 /usr/sbin

Thus you don't have to worry much about any of these commands being hijacked. And as long as you only use commands in these four protected locations you run no risk when invoking sudo if you specify full paths for all programs involved.


When invoking commands the Unix shell must first find them. It will know where to look thanks to an 'environment variable' known as $PATH. $PATH will typically contain the four 'bin' directories (in perhaps an arbitrary order).

% echo $PATH

The directories are searched in the order given; the colon (':') is used as a field separator. As soon as the shell finds a match it stops its search.

If the program foo is found in both /sbin and /bin and $PATH is as above only the copy in /bin will be seen (and run).

Running sensitive commands requiring privilege escalation is relatively safe as long as $PATH has not been tampered with and as long as all program files referenced in the commands are to be found in one of the four 'bin' directories.

Some systems add further directories to the standard $PATH variable; it's important to check these directories are also locked down just as tightly.

Alternative Sudo Authentication

By default sudo will require the password of an admin user already logged in. This has one drawback: if an interloper acquires the admin password the interloper by default also has access to the root account.

It is possible to configure sudo to instead demand the password for the root account, but this would necessitate enabling the root account - something better avoided.

But the last field in a user record denotes the program ('shell') that will be run on a successful login; were this shell set to /usr/bin/false the successful login would immediately exit again, incapable of causing any harm or doing anything at all.

[/usr/bin/false is a program that simply exits with a non-zero error code.]

And set the second last field - the login directory - to /var/empty to be doubly sure. [That's what it's there for.] And finally you give root a password - and of course not the admin password.

root:tNzaRKtRg7Xyf:0:0:Revolving Door Root Account:/var/empty:/usr/bin/false

[Of course this can - and should - be done differently today. On OS X Tiger systems or earlier it's NetInfo Manager.]

Once that's done you change the authentication requirements in /etc/sudoers. Add 'Defaults:rootpw' with visudo.

[Take a crash course in vi before attempting this.]

MOAB: Collateral Damage

One of the benefits of the Month of Apple Bugs was to make OS X users understand that security is up to them - that they themselves must be aware of security issues in their systems and things they shouldn't be doing or condoning in third party applications.

Again: a system only needs security if it either is or has something to protect. As security cannot be built into a system after the fact - vis Microsoft's dilemma with Windows - a good system has to have proper security at the user's disposal.

And a good system must foremost protect itself without waiting for a nod from its user. If the system goes down no one benefits. It must be assumed the system will stand.

Thus a good system must offer adequate means for a user to protect personal data. Third party applications for OS X have been both naïve and lax in their treatment of this data, often requiring admin passwords and thereafter storing them in the clear or at best with the negligible speed bump known as 'base64'. Now that OS X users are aware of how their security was outsourced they can do something about it.

And as a system becomes more complex there will be more ways to exploit it due to the interaction between the various components and software designers not seeing the full ramifications of the changes they make. Even clerical error can play a part as was noted here during that month.

Where the Buck Stops

At the end of the day security is the responsibility of the person who owns or runs the system. As ordinary users grow to understand more about how attackers can get at their systems and their information they become more capable of meeting the threats and eliminating them.

sudo is a powerful and above all very convenient facility in Unix but it can be used carelessly - and therefore it can also be compromised. And while the danger most people fear most is the worm outbreak the great majority of exploits occur with the black hat in a more direct contact with the target machine - 'inside the company'.

Attacks of today - the new professional kind - don't exhibit much ambition to cause widespread worm outbreaks anyway. There was very little money to be gained by the ILOVEYOU worm, the AnnaK worm, or Code Red. They caused a lot of damage but they weren't written with the dollar sign in mind. Today's new generation of attacks are of a completely different breed -s they single out specific computers or LANs and go for pure profit and nothing else.

It's therefore not enough to kick back and relax in the comfort that a worm outbreak is unlikely - for a concerted focused attack is, and today more than ever before.

It's not particularly difficult to take any Unix distro out of the box and set it up so it becomes the sorry part of a turkey shoot within minutes. For any of these systems to work adequately (and protect your data) you have to make sure they're configured properly and that you don't go do something you're not supposed to.

The Dos and Don'ts

Don't 'sudo' execute a script unless you can guarantee the contents of the script.
Your scripts are normally not owned by root and they're writable. Meaning anyone can corrupt them. And when they're run through a sudo command you're toast.

Watch out for sudo calls in scripts.
The same thing applies: you might not see changes made to your scripts and suddenly the bread is burning.

Make sure your Terminal is invoking a second login when you use it.
Your Terminal settings are in an unprotected file in your user area; they can be modified to effect an 'ordinary' shell session - something you generally don't want.

Don't run scripts requiring your password unless you check their contents.
This can't be stressed enough: it takes five minutes to write a password harvester that behaves exactly like sudo.

Check your running environment regularly.
$PATH can be compromised in a number of ways - and as pointed out above sudo won't do anything about it.

Live without ~/.bash_profile and ~/.MacOSX/environment.plist.
Both of these files can be used to compromise you by corrupting $PATH. If you find the former: remove it and close Terminal before using Terminal again. If you find the latter: remove it and log back in. Make a habit of checking for their existence before doing anything with sudo.

Eliminate your sudo time stamp entirely.
This will mean you have to authenticate each and every time but it also means nothing else can 'piggyback' in on your grace period. [By default the grace period is set to five minutes - click here for further info.]

Enable TTY tickets.
This thwarts another compromise: each interface will instead run in its own sudo context. [Click here for further info.]

Kill your time stamp when exiting Terminal.
Do this by executing either 'sudo -K' or 'sudo -k'.

Disable remote login.
By default this is on; turn it off.

CLIX & Sudo

CLIX and the ACP perform a number of checks and functions to protect you against command spoofing and $PATH hijacking.

  • CLIX automatically clears your sudo time stamp after every completed command.
  • CLIX automatically clears all vestiges of your password when your computer goes to sleep.
  • CLIX only allows commands in the traditional four locations to be accessed without their full paths.
  • CLIX performs internal consistency checks on itself to make sure nothing is compromised.
  • The ACP 'Resolve Path' Text service can check all paths before you run a command.

See Also
Sudo Fun
ACP Text Services
Too Much Sudo Fun
CLIX: Safer than Terminal?

TTY Tickets
'If you can't type - click.'
The Zero Time Stamp Timeout

Cookie Tin Tips I
Cookie Tin Tips II
Cookie Tin Tips III
Cookie Tin Tips IV
Cookie Tin Tips V

Cool Clever Stuff with CLIX
Cool Clever Stuff with CLIX II
Cool Clever Stuff with CLIX III

About | ACP | Buy | Industry Watch | Learning Curve | Search | Test Drive
Copyright © Rixstep. All rights reserved.