Strategies for for working with Sudo

Identity


The sudo command helps you stay busy without getting exposed. We examine some techniques for working with sudo.

By James Mohr

Nigel Silcock, Fotolia

Rather than allowing users to log in directly to the root account, system administrators often turn to the su command. su allows you to switch to a new user and operate with the permissions of that user. The drawback of this approach is that the su user can do anything the target user can do.

Many companies think it is a sufficient safeguard to require users to log into their own account, then do a su to root to perform the required tasks. This solution is convenient because you only need to ensure everyone has access to the root password, but it has the added security problem that anyone with a root password actually becomes root and can do anything they want.

A good alternative is the sudo command. Like su, sudo lets you execute a command as the target user, but once the command is completed, you are back to the original user context. Actually, you can run su so that only a single command is executed, but sudo lets you restrict access further and in number of powerful ways.

Be careful how you use it - if sudo is improperly configured, it can leave you almost as vulnerable as you were without it. In this article, I will explore some techniques for working with sudo.

Limiting Without Restricting

I have seen many administrators use sudo simply as a modified version of su, running every possible command as root. Although the act of re-invoking the command with each instruction provides an extra reminder of the need to be careful, all one needs to do is to use sudo to start bash, for example, and the session is basically the same as if you had run su. Some administrators turn things up a notch and limit which commands can be executed, but even that only touches the surface of what sudo can do.

The default configuration on many Linux distributions allows users to run any command via sudo as root, provided they have the root password. If this is your desktop machine and you have the root password anyway, using sudo instead of su is still a good habit. Many administrative tasks started through the KDE GUI are actually started by kdesu, which prompts you for the root password before continuing (Figure 1).

Figure 1: KDE uses kdesu to prompt for the root password.

With sudo, simply having the target user's password is not the only thing - you are limited to the commands defined in the sudo configuration file /etc/sudoers. To edit this file, you are provided with visudo, which first makes a copy and then replaces the original when you finish. Prior to the file saving, a syntax check is performed and, should an error be found, a message is displayed indicating the line number and the type of error, which gives you the opportunity to re-edit the file. You can exit without saving, or save the changes anyway, which will cause a warning from the system (Figure 2).

Figure 2: Visudo reporting on a syntax error.

Configuring sudo

In the default sudoers file, typically only a handful of options are defined. These options are divided into three types of directives. The first type defines certain default behaviors. The settings can be booleans (on/off), integers, and strings. Typically there is one directive per line, but if it is too long, you continue in standard Linux-fashion by ending the line with a backslash (\).

When defining defaults, the line has the general format:

Defaults option

For example:

Defaults env_reset

This entry tells sudo to reset environment variables to those of the target user. env_reset goes hand-in-hand with the env_keep parameter, which contains a list of environment variables to keep. By default, what is kept is usually related to various language and location variables. (This is actually a security feature because a user could set their path so that non-standard directories are searched first, and if the path variable is not reset, you have the potential for executing other commands as the target user. For example, a shell script started through sudo, which uses find, could be tricked into starting /tmp/find with potentially dangerous consequences.

By default, sudo will run as root. You can change this behavior by specifying -u to the sudo command. Many users have the misconception that sudo simply means the command will run as root. Although this is probably the most common way sudo is used, it is not always necessary or even desired. For example, often a user account has environment variables that root does not have.

Another security-related option is targetpw. This option says that sudo will prompt for the password of the target user. If it is not set, sudo will prompt for the password of the invoking user.

Keep in mind that these settings are defaults. You can configure specific commands (or sets of commands) so that environment variables set on the command line are not removed if the default is configured to do so. See the sudoers man-page for details.

The syntax may be confusing at first, but in my experience, you quickly get the hang of it. The general format of these entries is:

user_alias host_alias = (runas_alias) tag command_alias

Note that alias does not mean that you can only use aliases, because each entity is an alias for itself. For example, you could specify a user, command, etc. without explicitly having to define an alias beforehand.

Because the first entry is the user, these are referred to as user specification lines. You are likely to find a line that looks like this:

ALL ALL=(ALL) ALL

Be aware of this because it allows all users to run sudo for all target users from all hosts and run all commands.

Because you are still required to input the password of the target user, this is not a free pass to do anything on the system you want; however, this does provide the additional security of not having to start an unlimited session as the target user.

You will likely also find an entry like:

root ALL=(ALL) ALL

This entry is essentially the same thing as the previous command, but it applies only to the root user. The command explicitly allows root to run all commands as all users.

A useful mechanism is the ability to define aliases, which are typically used for lists of the various objects (for example, a list of operators within the company who have similar functions). Alias definitions all have the same basic format:

alias_type space alias_name = object1, objects2, ...

When listing objects, you are not limited to standard objects, such as users in /etc/passwd, or specific hosts, but you have a wide range of options. (See the sudoers manpage.)

In my experience, grouping objects into aliases makes complex configurations easier to manage. If different sets of people are allowed to run different sets of commands, aliases help ensure that everyone has access to the correct commands. Modifications can then be made in one place, rather than being spread through the file.

The runas_alias option defines the target user for a list of commands. As with other objects, you can have multiple runas_aliass on the same line. For example, some commands you want to run as root, whereas others you only want to run as a less privileged user.

A command_alias consists of individual command names, directories, or other command aliases. There are a couple things to note here. First, the command name must be fully qualified (that is, it must include the full path). If you specify a command that is not fully qualified, visudo will view this as as a syntax error.

If you simply list the command name, you can then specify any options or parameters on the command line. Depending on the circumstances, that might not be a good thing. To limit what a specific user can do, you explicitly define what options are allowed.

Note that all arguments must match exactly unless the command was specified with wildcards. If you use an asterisk, it will match any arguments (or none at all) just as if you had specified no wildcards all.

Each entry can have zero or more tags associated with it. The most common tag I have seen is NOPASSWD, which indicates the commands are run without first prompting for the specific password. This NOPASSWD tag is paired with the PASSWD tag, which forces you to supply the appropriate password. (Requiring a password is the default.) Combining all of these options together, you might end up with something like the following:

jimmo ALL = (operator) /bin/more /var/log/messages, (root) NOPASSWD: /sbin/fdisk -l

Here, the user jimmo from all hosts is allowed to run more as the user operator but only on the file /var/log/messages. The user can also run /sbin/fdisk -l as root without having to input a password. Note that, in both cases, the arguments are explicitly defined. Using other arguments (e.g.,. /sbin/fdisk /dev/hda) will cause sudo to prompt for the appropriate password.

Security Dangers

Like any other security-related feature of your system, sudo can open a lot of holes if you're not careful. Some of those holes might result from not configuring sudo properly. Others problems arise from misunderstanding the natural behavior of the command you specify along with sudo.

In other cases, you might be aware of the command's behavior but simply overlook specific ramifications of that behavior. For instance, one important admin task is to react when filesystems get too full. Naturally, if you don't have the necessary permissions, you are going to have trouble cleaning up the filesystem. In one case I am familiar with, this problem was addressed by configuring sudo so operators could use gzip. The rationale was that they could then compress log files and free up space.

This solution demonstrates two problems. The first problem is the attitude of the system administrators requiring the operator to react to the problem on the fly rather than proactively configuring the system to compress the log files automatically. The second problem is that when gzip is finished compressing the file, it removes the original.

To enable the operators to compress any log file, gzip was specified with an asterisk, meaning it could be run on any file. It is therefore possible for someone to compress a file that is actually necessary for normal operation of the system. A very simple example would be the /etc/passwd file. If a user were to compress this file via sudo, the original would disappear and a great many things on the system would stop working correctly.

The same office was having problems with runaway processes. The solution was to allow the operators to kill these processes via sudo. As with gzip, the kill command was specified with an asterisk, which meant the user could kill any process.

Both these cases require you to make some assumptions about the trustworthiness of the operators. On the other hand, if your goal is to make the system as secure as possible, including preventing people from doing things they shouldn't do, allowing a user to delete any file or kill any process poses a number of security problems.

The next danger comes from overlooking the natural behavior of the command you specify. For example, when troubleshooting problems, it is often necessary to look at various log and configuration files. In some cases, it might be the operator's job to do the initial troubleshooting by looking through the files. Rather than taking the time to define which files need to be read by which users, you might be tempted to allow the users to run the more command to page through any file on the system.

Once again, any means any. Some files shouldn't be read by just any user, (for example, files that contain passwords). Even if you trust your users enough to allow them to look at these files, you have to worry about what would happen if an intruder gained access to a user's account.

Another problem with the more command is that it allows you to execute a shell escape, which lets you start a sub-shell from within the more command. Because more is started as root, for example, all sub-processes, including any shells, run as root. This means you now have a shell running as root, and you have complete control over the entire system! To make matters worse, I have seen some installations where this is possible without even entering a password to run the command, which means you can gain access to root shells to your heart's content.

One solution to this problem is not allowing users access to programs with a shell escape option. If all the user needs to do is look at the contents of a file, you might be able to get away with using something like the cat command, which does not have shell escapes. If the file is long, you might not get it all on the screen using cat. That's not a problem, because you can simply pipe the output through more. Because the more process is not run as the target user (i.e., root), doing a shell escape simply brings you back to the original user.

Although this approach addresses specific commands, it might catch you off guard if you run across a program that allows shell escapes where you didn't expect them. To address this issue, sudo provides mechanisms to prevent commands from running shell escapes. The first option is to set the default to noexec:

<C>Defaults noexec<C>

The noexec setting will apply to all commands by default, regardless of which user starts them and which user is the target. Alternatively, you could disable shell escapes on a command-by-command basis with NOEXEC:

jimmo ALL=NOEXEC /usr/bin/view, /usr/bin/more

Sudo does a good job of keeping track of who did what and whether they were successful or not. By default, sudo logs events using the syslog service; however, you can explicitly define a log file by using the logfile default entry in /etc/sudoers. Furthermore, you can define different syslog facilities and priorities as you see fit. See the sudoers manpage for more details.

Conclusions

As with other security tools, the safest strategy for using sudo is to disable all access and then enable what you need, piece by piece. Keep in mind the intrinsic ability of Linux shells to run commands together through pipes.

Before you start designing system administration procedures for your environment, it is a good idea to make sure you know exactly why you are using each command and each argument you run with sudo. Perhaps you can find better solutions (such as preventing runaway processes), or at least more secure ways of specifying commands. Err on the side of security, not convenience.