Be aware of these limitations when configuring sudo.
sudo is a handy utility for giving out some, but not all root privileges to users of Unix and Unix-like systems. sudo has some limitations and gotchas, however.
6.9.1 Limitations of sudo
Tools like sudo exist because the standard Unix privilege model is monolithic. That is, you are either root, with all the privileges and dangers attendant, or you aren't, in which case you lack the ability to affect the system in significant ways. sudo is a workaround of this model. As such, there are limits to what it can achieve, and many of these limitations show up in interactions with the shell. For example:
% sudo cd /some/protected/dir Password: sudo: cd: command not found
Because a process cannot affect the environment of its parent, cd can't be implemented as a program external to the shell. The command is therefore built into the shell itself. sudo can confer privilege only on programs, not pieces of programs. So, the only way to cd to a protected directory using sudo is to execute the shell itself with sudo:
% sudo bash # cd /some/protected/dir # pwd /some/protected/dir
A workaround is to write a script like the following:
#!/usr/local/bin/bash cd /some/protected/dir;/bin/ls
If you enable access to this command in /usr/local/etc/sudoers, authorized users will be able to ls the contents of a protected directory. This won't allow you to cd to a protected directory, but it will allow you to do work in one.
Another possibility is to allow the user to run a restricted shell, for example, bash -r. This is not a good general solution, though, since most such shells are very restrictive. For example, bash -r disallows use of cd!
Another interaction between the shell and sudo involves I/O redirection.
% sudo echo "secret stuff" > /some/protected/dir/secret bash: /some/protected/dir/secret: Permission denied
The problem here is that the bash shell does the I/O direction, not the echo command. This time there is a workaround, however:
% echo "secret stuff" | sudo tee -a /some/protected/dir/secret \ > /dev/null % sudo cat /some/protected/dir/secret secret stuff
Here we use sudo to run tee with the -a (append) switch, which dumps the I/O stream coming from stdin to a file. We throw away the stdout stream since we just want the file. Now sudo can confer privilege on the program tee, and we get the desired result, although it's a bit awkward.
The same problem exists when trying to redirect stdin. In this case, we can use the similar, but less unusual, expedient of sudo cat to get at the data.
The following interaction is not really a limitation, but more of a wart:
% sudo cat /some/protected/dir/secret | wc | sudo tee \ /some/protected/dir/count > /dev/null Password:Password:
Here we have no cached credentials, so sudo prompts us for our password. But since there are two sudo commands in the pipeline, we get two password prompts, one right after the other. When we enter our password and press Return, nothing happens our cursor stays put on the next line. We are actually at the second password prompt, but there is no indication of this. Entering our password again will get us out of the mysteriously hung pipeline.
6.9.2 sudo Configuration Gotchas
sudo is very flexible. The /usr/local/etc/sudoers file has rich semantics to implement a nearly infinite set of policies that can range from very open to very restrictive. Of course, open policies are easier to understand and implement than the restrictive ones, because there are so many ways to subvert many seemingly restrictive policies.
The earlier examples of sudo limitations assumed that all the commands used were authorized for our use in the sudoers file. However, both cat and tee are dangerous commands that could allow a user to easily take control of a system. (Consider sudo tee /etc/spwd.db < myevilspwd.db.) This underlines the generic risk of enabling commands with sudo. It is difficult to analyze all the possible ways a particular command could be misused to subvert a closed security policy. The more commands you enable with sudo, the harder this task becomes. In general, beware of commands that are capable of modifying files, such as editors, dd, cat, and tee, or those that allow shells to be run from within them, such as emacs and vi.
You can try restricting what arguments can be given to dangerous commands, but beware of alternate methods for supplying those arguments. For example, the following configuration entry recently came up on the sudo-users mailing list:
Cmnd_Alias PASSWD = /usr/bin/passwd, !/usr/bin/passwd root
This works great if the user types passwd root:
% sudo passwd root Sorry, user test is not allowed to execute '/usr/bin/passwd root' as root on ****.
% sudo passwd -l root Changing local password for root New Password:
Oops! The addition of the -l flag causes the pattern in the sudoers file not to match the equivalent command.
The moral is: to restrict parameters in sudoers, you must disallow all permutations of arguments and switches that you deem undesirable.
man sudoers warns about another danger:
It is generally not effective to "subtract" commands from ALL using the '!' operator. A user can trivially circumvent this by copying the desired command to a different name and then executing that. For exam- ple: bill ALL = ALL, !SU, !SHELLS Doesn't really prevent bill from running the commands listed in SU or SHELLS since he can simply copy those commands to a different name, or use a shell escape from an editor or other program. Therefore, these kind of restrictions should be considered advisory at best (and rein- forced by policy).
6.9.3 Shell Access with sudo
Authorizing shell access with sudo obviously opens your security policy to the largest possible extent, since any available command can then be run in the root-enabled shell. This may be exactly what you want, but you also lose sudo's audit trail, since subsequent commands issued from the shell are not logged.
One way to allow shell access to trusted users without losing the audit trail is to use sudoscript [Hack #62] .
6.9.4 See Also