Most mature operating systems -- IBM's MVS, DEC's VMS,
and HP's
MPE, for example -- provide a number of privileges,
many of which
are limited in scope, that can be assigned one at a
time to users
on the system. On UNIX, however, you either have super-user
privileges
or not -- all or nothing. Generally, the super-user
privileges
are given to one user, root. This means root has to
be available for
any of a number of tasks, including lp administration,
mounting/unmounting
disks, changing network configuration, adding users,
shutting down
a system, and running backups.
Working around this inconvenience can cause a number
of security issues
for a system. If you give root's password to everyone,
you violate
basic password security and lose the ability to find
out who performed
a command as root. Being able to log on as root from
anywhere is always
a bad idea and allowing several people to do this is
worse, since
it greatly increases the likelihood that a root terminal
session will
be left unattended. Anyone with physical access to a
terminal left
in such a state has root access. It only takes minutes
to extend privileges
or subvert the system.
Under certain circumstances, however, it's useful to
be able to delegate
some privileges. It may be that a networking staff,
rather than the
system administrator, is responsible for the networking.
Operators
may need to back up files. Perhaps a manager has a team
of support
personnel and does not want the root password to be
that widely known.
This last was the case for a recent customer of mine.
The organization
had about 500 workstations that were supported by a
staff of 20. All
these systems had the same root password, which was
changed weekly.
The major concern was keeping track of what had been
done on each
of the systems by any of the support personnel. To this
end, the root
log-on was only used when mandatory and was restricted
to the system
consoles. In place of the root log-on, they used a program
called
sudo (super-user do), which allows them to execute commands
with super-user privileges and logs this activity.
sudo is a set-user-id program that runs as root and
allows
authorized users to execute commands for which they
are approved.
sudo was originally written by Cliff Spencer of SUNY-Buffalo
and was
published in Evi Nemeth's UNIX System Administration
Handbook.
It was originally written to run under BSD UNIX.
The original sudo left a number of things undone. These
included
being able to shell out of programs like vi, using root's
path,
having to fully qualify the commands to be executed,
having to specify
all the commands that can be executed and not being
able to specify
commands that cannot be executed, and being able to
specify "all"
commands, thereby allowing a user free range. A user
could also sudo
a shell and thereby circumvent the logging mechanism.
The original sudo used root's complete environment,
including
root's shell and path. I added the putenv commands to
set the
shell to /bin/false and assigned a path for commands
that can
be run by sudo. Reassigning the shell variable keeps
programs
like vi from being able to spawn a subshell. Assigning
a path
limits the scope of the commands that can be executed
with sudo.
It also eliminates the need to fully qualify path names
for commands.
I added a "not" option to the configuration
file to allow
you to configure someone to run all commands except
those listed.
Granting some super-user privileges to ordinary users
and depending
on their log-in passwords for security is likely to
cause security
problems. If a user who has sudo privileges has a poor
password,
or shares the password, or has it stolen, then the super-user
privileges
granted to that user have also been compromised. There
are a number
of things that you can do to limit this risk:
Monitor the log files to see what the users are doing.
Some commands should not be given out to sudo users.
For example,
certain commands circumvent the logging procedure. These
are commands
that spawn an interactive shell or replace the sudo
process with another
process. These include sh, ksh, csh, rsh
(restricted shell), and exec. Other commands increase
the
risk to other systems, particularly in a Trusted Computer
Base. These
are rlogin and remsh (remote shell, rsh on some
systems). These programs allow you to log-on to another
computer without
requiring a password. Still other commands, such as
chmod and
chown, can be used to coerce additional permissions
and can
be used to make set-uid shells that can be executed
outside of sudo.
Security Measures
A number of steps should be taken to ensure that you
are using sudo
securely. This section describes those steps.
The locations of the configuration file, log file, and
time directory
should be known only to the security manager. Any user
who knows where
these files are located can manipulate them to add users
or commands
to the configuration file, or to add commands in the
secure path to
be executed via sudo, or to alter the logfile. One way
to obscure
the location of these files is to put them in a hidden
directory,
that is, a directory whose name starts with a period,
with no read
or write permission for anyone and root ownership. A
directory name
that cannot be typed would actually be better. Only
commands that
are to be executed would be placed in this directory,
and permissions
for these commands would be execute only, no read or
write permissions.
The source code should not be left online and the binary
file should
be marked as execute only, with no read or write permissions
for anyone.
Failure to observe these guidelines would allow someone
to locate
the path to the configuration and log files and time
directories.
How sudo Works
sudo first validates its configuration. It checks that
it is
owned by root and has the set-UID bit set. It checks
the configuration
file to validate that it is not writeable or readable
by anyone other
than root (the configuration file contains the list
of authorized
users and the commands that they can execute). sudo
next validates
the user, by scanning through the configuration file
to find the user's
log-on name, and the command that was entered, by scanning
the list
of commands that are valid for that user. It then prompts
the user
for a password and matches the input password against
the user's log-on
password. Only when all of these tests have been passed
will it execute
the command. This command, however, must be in a path
that is defined
in the sudo source as a secure path. If there is a configuration
problem or if a user is not authorized or tries to execute
a command
for which he has no permission, sudo sends mail to the
security
manager describing the problem. sudo also logs all executions,
whether they are successful or not.
Configurable Parameters
There are a number of locally configurable parameters
at the beginning
of the sudo source code. The following are the default
values:
#define SECURE_PATH "/bin:/usr/bin:/etc"
#define USERFILE "/usr/local/adm/sudoers"
#define LOGFILE "/usr/local/adm/sudolog"
#define TIME 5 /* minutes */
#define TIMEDIR "/usr/local/adm/sudocheck/"
#define SUDO_COP "root@localhost"
SECURE_PATH is a path statement that defines the
directories that contain the programs that can be executed
by sudo.
Appropriate permissions need to be maintained for the
directories
in this path and the programs in these directories.
Periodic checksumming
of these directories would be a good idea.
USERFILE is the configuration file that contains the
users
and the commands that can be executed. The format of
this file is
user log-on name, followed by a white-space-separated
list of commands.
You can use "not" to indicate all but the
listed commands.
You can use "all" to indicate all commands
in the secure path.
LOGFILE is the location of the log file that sudo creates
to log information about commands that were executed
or attempted.
This file must not be readable or writeable by anyone
but root.
TIME and TIMEDIR allow a user to enter a number of sudo
commands without re-entering his or her password if
the TIME
has not expired. This is managed by making timestamp
files in the
TIMEDIR directory. Setting TIME to 0 disables
this option. This directory also needs appropriate permissions.
SUDO_COP is the mail address of the security manager,
where
information about violations is to be sent. The mail
address must
be in a format understood by the mail system running
on the node where
sudo is installed.
Configuration File
The configuration file consists of the user's log-on
name followed
by the commands that the user can execute, or the word
"not"
followed by the commands that this user cannot execute,
or the word
"all," indicating that this user can execute
all commands.
The following lines represent three users: the user
"operator,"
who can execute the du and dump commands; the user "nice_guy,"
who can execute all sudo commands, and the user "buster,"
who cannot execute the command sh.
operator du dump
nice_guy all
buster not sh
Only commands that are in the secure path can be executed
with sudo.
Log File
The log file contains the date and time that sudo was
executed,
whether it was successful or not, who executed sudo,
and the
command line used with the sudo command. Here is an
excerpt
of a sudo log file:
Mon Aug 15 9:25:42 : SUCCESS buster vi /etc/hosts
Mon Aug 15 11:30:05 : FAIL operator lpshut
Tue Aug 16 22:02:46 : SUCCESS buster mv rouge/bin
Thu Aug 18 8:05:21 : FAIL hacker vi /etc/passwd
Fri Aug 19 16:54:02 : SUCCESS nice_guy shutdown -h
Using sudo
Using sudo is generally very straightforward. You invoke
the
sudo command, followed by the command and parameters
that you
wish to execute with super-user privileges. For example,
to edit the
password file you would type:
sudo vi /etc/passwd
Some situations are not so obvious. If you are pipelining
commands, you have to invoke sudo for each command in
the pipe
that requires super-user privileges. For example, if
you wish to find
all the files on the system and create a cpio archive
on a
tape drive that has write permissions only for root,
you would use
the following command:
sudo find / -print | sudo cpio -o >/dev/rmt
You can combine remote execution with sudo to
execute commands on remote systems that support sudo.
For example,
if you wish to print all the failed log-in attempts
of a remote system
on a local printer, you would use:
remsh remotehost sudo who </etc/btmp | lp
The lp command does not have to be invoked with
sudo since the output from the who command is available
across the pipe without privileges.
Enhancements
It would be convenient to have the ability to enable
a group of users
for a list of commands. You could accomplish this by
adding a group
command to the command file, followed by a list of the
users who are
members of the group.
I have also had requests to add a node name to the log
file for systems
that share file systems. With the current configurations,
it is impossible
to tell on which node the sudo command was executed.
The only
change required would be a simple change to the logging
routine, but
I contend that if the nodes share a file system, then
a security problem
on one is a security problem on all.
Conclusion
Some vendors are starting to address the issue of granularity
of control
in UNIX, but currently their efforts are very limited
and vendor specific.
Until standards for subdividing and assigning privileges
are more
widespread, sudo, which is easily portable, can be a
useful
tool if appropriate security precautions are taken.
It allows system
administrators to delegate tasks while maintaining system
security
across UNIX systems from many vendors.
About the Author
Don Pipkin has been a Hewlett-Packard technical consultant
for nine years, focused on UNIX. He specializes in system
security
and networking Client/Server technologies. He has a
BS in Computer
Science from the College of Engineering at the University
of Tulsa.
Don can be reached at Hewlett-Packard, 6655 S. Lewis
#105, Tulsa,
OK 74136, or at pipkin@hptulsa.ssr.hp.com.