sections in this module City College of San Francisco - CS260A
Unix/Linux System Administration

Module: Permitting Privileged Operations I
module list

sudo

sudo is a program that allows specific users to execute specific commands as other user(s), as indicated by the rules encoded in the sudoers file /etc/sudoers. Privileges about what can be done by whom can be granted with whatever granularity is desired. It is easy to encode capabilities such as these:

sudo is used by simply preceding the command that requires privileges with sudo:

sudo [ -u user ] command

Normally, sudo is used to execute a command as root. This is the default unless -u user is used to specify who to run the command as. By default, sudo will request a password. This is the password of the user running sudo, not of the user he or she wants to become. This ensures that the sudo user is actually the user who logged in (i.e., a guard against someone using your terminal when you step away)

You can inquire about your abilities to run commands using sudo by the command sudo -l   A listing of the commands you can execute via sudo and who you can execute them as is output.

Plusses of sudo

Minuses of sudo

Overuse of sudo

Some linux systems, as installed, force the use of sudo to perform any operation as root, but allow any user to use it. The purpose of this is to limit root privileges to executing a single command at a time, and to log the commands that are executed. The true power of sudo is its ability to allow privileged operations on a user-by-user basis.

Warnings

sudo's task is to provide the privileges encoded in the sudoers file strictly. It has no idea what the commands do. It is only responsible for whether the user can execute them. Once the command has been started by sudo, the user can do whatever the command allows them to do.

For example, it would be easy to create a rule in sudo to let gboyd run the command bash as root. sudo is responsible for ensuring that only gboyd can run the command and that only bash can be run. It has no idea what gboyd can do with bash. Of course, gboyd now has a shell running as root and can do whatever he desires. Such a rule would be silly.

The issue is this: if a user is allowed to start a privileged process, he or she can do whatever the process can do. If the process starts child processes, the children inherit the privileges from their parent. You must therefore know exactly what a command is capable of before granting privileged access to it.

Each entry in the sudoers file specifies

user hosts = [ (runas) ] [ NOPASSWD: | PASSWD: ] [NOEXEC:] cmd

Each field (user, hosts, runas, cmd) can be a single item or a comma-separated list of items. Each can also be a sudo alias, as explained later. We will discuss the format of each of these parts of the sudo command in its own section following.

The optional keywords NOPASSWD: or PASSWD: govern whether the user will be required to enter his or her user password before executing the command. PASSWD: is the default. The NOEXEC: keyword, if specified, will try to run the command with a patch that will cause the exec() system call to fail. This should effectively suppress shell escapes. Note: the NOEXEC: keyword will only work on native dynamically-linked executables on systems that support LD_PRELOAD, such as Linux.

In each field, the keyword ALL can be substituted to indicate "all possible". Thus, 

Thus, on a system that allows any user to execute any command as anyone (default: root) without giving their password first, you might see the sudo rule

ALL ALL = (ALL) NOPASSWD: ALL

This rule is used to simply log all actions of root, and is used by the system owner, who is not given a root password. It thus substitutes for logging in as root and provides an accounting trail. This rule appears on current versions of Mac OSX and Ubuntu linux, with the exception that the users who execute it may be limited to those who are members of a particular group, such as admin:

%admin ALL = (ALL) NOPASSWD: ALL

The sudoers file is divided into sections, in this order:

  1. Host Aliases section. This section contains the Host_Alias definitions (if any). We will not discuss the hosts format, nor the Host Alias section, as we are concerned with sudo running on the standalone machine. The interested user is referred to the sudoers man page. Instead, we will use ALL in place of the hosts field to indicate "all applicable hosts".
  2. User Aliases section. This section contains the User_Alias definitions (if any). We will discuss the User_Alias definitions when we describe the user format. User_Aliases may be used in the runas field as well.
  3. Cmnd Aliases section. This section contains the Cmnd_Alias definitions (if any). We will discuss the Cmnd_Alias definitions when we describe the cmd format.
  4. Defaults section. This section may change the settings of various sudo parameters from their default settings. For brevity, we will not discuss this section. The interested reader is referred to the man page on the sudoers file. (Have fun!)
  5. The sudo commands themselves. These are in the format of a sudo command, with the various fields previously discussed:

user hosts = [ (runas) ] [ NOPASSWD: | PASSWD: ] cmd

Alias names

Aliases associate a name with a list of possibilities, as discussed below. Alias names may contain uppercase letters, numbers, and the underscore. They must begin with a letter, and may NOT contain any lowercase letters.

Specification of user and runas

The user field can be a comma-separated list of users, uids, User_Aliases, and groups. Groups are indicated by the prefix %. An individual user may also be specified by their uid prefixed by #, and may be negated by a prefix of !. Thus, if the user field is

gboyd,OPERATORS,!randy,%sys,#0

and OPERATORS is a User_Alias, the sudo command may be run by the individual user gboyd, any of the users indicated in the  User_Alias OPERATORS, any member of the group sys, the user with uid 0, but not by randy.

A User_Alias associates the alias name with a comma-separated list of users, in the same format as above. Thus, we could create a User_Alias named SYS to include the users above like this:

User_Alias SYS = gboyd,OPERATORS,!randy,%sys,#0

Note that a User_Alias can include another User_Alias. (I assume OPERATORS must be defined before SYS.)

The runas field has the same syntax as the user field, and uses User_Aliases.

Specification of hosts

As mentioned previously, we will not discuss this field, nor its aliases. Instead, we will use the placeholder ALL to indicate "all applicable hosts".

Specification of cmd

The cmd field can be a comma-separated list of commands and Cmnd_Aliases. Each command can be one of these formats:

Thus, if the cmd field is

/bin/ls, /bin/cat /var/log/messages, /sbin/sudocmds, /sbin/shutdown -h now, SYS_CMDS

where SYS_CMDS is a Cmnd_Alias and /sbin/sudocmds is a directory, the following commands may be run:

A Cmnd_Alias associates the alias name with a comma-separated list of commands, in the same format as above. Thus, we could create a Cmnd_Alias named MY_CMDS to include a few commands like this:

Cmnd_Alias MY_CMDS = /bin/ls, /bin/cat /var/log/messages, /sbin/shutdown -h now

Again, a Cmnd_Alias can include another Cmnd_Alias

Examples

Consider the sudo line

gboyd   ALL=(root) /usr/local/bin/doit ""

This allows gboyd to run the command /usr/local/bin/doit as root, so long as he does not try to give the command any arguments. It also does not allow him to run the command as anyone else (other than root). Note that if doit is in gboyd's PATH, he does not need to indicate the absolute path. (In other words, if, when gboyd executes the command doit, doit is resolved to /usr/local/bin/doit, gboyd can use sudo to execute doit.)

The sudo line

student ALL=(ALL) NOPASSWD: /bin/cp * /usr/local/bin

allows the user student to copy anything she wants to /usr/local/bin as any other user. An attempt to copy anywhere else fails.

[student@lenny ~]$ sudo cp child /usr/local/bin
[student@lenny ~]$ sudo cp child /bin
Sorry, user student is not allowed to execute '/bin/cp child /bin' as root on lenny.acrc.ccsf.edu.
[student@lenny ~]$

The sudo line

%users,!gboyd ALL=(bin) NOPASSWD: /usr/local/bin/upd ""

allows all members of the group users except gboyd to execute the /usr/local/bin/upd command, so long as they don't specify arguments. They do not need to enter their password when they run the command, but they can only run the command as the user bin. Thus, unless they use the -u bin option to sudo, permission will be denied (as without -u bin, sudo will attempt to run the command as root).

The last sudo lines

gboyd,francis,susan,jamal,alfonzo,tarzan ALL= /sbin/shutdown -h *

gboyd,francis,susan,jamal,alfonzo,tarzan ALL= /sbin/shutdown -r *

allows all of these users to execute the shutdown command, so long as either the -r or -h option is used. The wildcard at the end of the command allows the user to provide a shutdown message This last set of commands could be simplified using aliases:

User_Alias  OPERATORS = gboyd,francis,susan,jamal,alfonzo,tarzan

Cmnd_Alias SHUTDOWN = /sbin/shutdown -h *, /sbin/shutdown -r *

OPERATORS ALL = SHUTDOWN

There are several sources of errors when you are writing entries for the sudoers file

A final warning

Make sure that any command you allow to run under sudo does not allow a shell escape. Remember, sudo is only responsible for starting the command. It has no control over what the command does. 

For example, a simple task to put under the control of sudo would be to allow others to review the system messages log file. Thus, a tempting sudo entry would be

ALL ALL= /bin/more /var/log/messages

If the user then ran sudo to use more on the messages file as root, the first page of the log file would be displayed:

run of sudo on 'more /var/log/messages', showing the
          first page of the log file with the 'more' prompt at the
          bottom

When a shell escape is used at the more prompt, the result is to start a new shell as root!

Feb 24 10:09:41 lenny dhclient: DHCPREQUEST on eth0 to 147.144.23.30 port 67
Feb 24 10:09:41 lenny dhclient: DHCPACK from 147.144.23.30
Feb 24 10:09:41 lenny dhclient: bound to 147.144.23.57 -- renewal in 8713 seconds.
!bash
bash-3.00#  id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=root:system_r:unconfined_t
bash-3.00#

Thus, our seemingly harmless sudo line has given everyone access to the root account.

This problem is easy to remedy. The foolproof way is to know which programs allow shell escapes, and simply replace the entry with a different, safer tool. In our example, use

ALL ALL= /bin/cat /var/log/messages

Then users can simply send the output of cat to more. The more process is not initiated by sudo, thus it is not privileged:

sudo cat /var/log/messages | more

The more elegant solution simply adds the NOEXEC: keyword to the command, as follows:

ALL ALL= NOEXEC: /bin/more /var/log/messages

Now when a shell escape is attempted, it fails.

As discussed earlier, there are some limitations on the effectiveness of NOEXEC:, and sudo can't easily determine this. If you have any questions about whether it will work on your system, just avoid giving sudo access to programs that have a shell escape.


Prev This page was made entirely with free software on linux:  
the Mozilla Project
and Openoffice.org    
Next

Copyright 2015 Greg Boyd - All Rights Reserved.