Grupo sudo: sudo does not ask members of this group for a password. sudoedit If a user who is not listed in the sudoers file tries to run a command via sudo, mail is sent to the proper authorities, as defined at configure time or in the sudoers file (defaults to root). Note that the mail will not be sent if an unauthorized user tries to run sudo with the -l or -v flags. This allows users to determine for themselves whether or not they are allowed to use sudo. ================================================================================================= Precauciones Never permit the following programs to be invoked with root privileges by sudo: su, sudo, visudo, any shell, and any program having a shell escape (vim, permite ejecutar órdenes). Be meticulous about specifying argument lists for each command in /etc/sudoers. If you aren't careful, even common commands like cat and chmod can be springboards to gain root privileges: $ sudo cat /etc/shadow > my.evil.file $ sudo cat ~root/.ssh/id_dsa > my.copy.of.roots.ssh.key $ sudo chmod 777 /etc/passwd; emacs /etc/passwd $ sudo chmod 4755 /usr/bin/vim (root-owned with a shell escape) Obviously, never let users invoke a program or script via sudo if the users have write permissions to the script. For example: /etc/sudoers: smith ALL = (root) /home/smith/myprogram would be a very bad idea, since smith can modify myprogram arbitrarily. If users have sudo ALL there is nothing to prevent them from creating their own program that gives them a root shell regardless of any ’!’ ele‐ ments in the user specification. ================================================================================================= Recetas ================================================================================================= 5.4.1 Problem You want one user to run a command as another user without supplying a password. 5.4.2 Solution Use sudo's NOPASSWD tag, which indicates to sudo that no password is needed for authentication: /etc/sudoers: smith ALL = (jones) NOPASSWD: /usr/local/bin/mycommand args smith ALL = (root) NOPASSWD: /usr/local/bin/my_batch_script "" 5.4.3 Discussion By not requiring a password, you are trading security for convenience. If a sudo-enabled user leaves herself logged in at an unattended terminal, someone else can sit down and run privileged commands. That being said, passwordless authorization is particularly useful for batch jobs, where no human operator is available to type a password. Recipe 5.5 Forcing Password Authentication in sudo 5.5.1 Problem You want sudo always to prompt for a password. 5.5.2 Solution When controlled by superuser: /etc/sudoers: Defaults timestamp_timeout = 0 systemwide Defaults:smith timestamp_timeout=0 per sudo user When controlled by end-user, write a script that runs sudo -k after each sudo invocation. Call it "sudo" and put it in your search path ahead of /usr/bin/sudo: ~/bin/sudo: #!/bin/sh /usr/bin/sudo $@ /usr/bin/sudo -k 5.5.3 Discussion After invoking sudo, your authorization privileges last for some number of minutes, determined by the variable timestamp_timeout in /etc/sudoers. During this period, you will not be prompted for a password. If your timestamp_timeout is zero, sudo always prompts for a password. This feature can be enabled only by the superuser, however. Ordinary users can achieve the same behavior with sudo -k, which forces sudo to prompt for a password on your next sudo command. Our recipe assumes that the directory ~/bin is in your search path ahead of /usr/bin. 5.5.4 See Also sudo(8), sudoers(5). ================================================================================================= Recipe 5.6 Authorizing per Host in sudo 5.6.1 Problem You want to allow a user authorization privileges only on certain machines. 5.6.2 Solution First, define a list of machines: /etc/sudoers: Host_Alias SAFE_HOSTS = avocado, banana, cherry Let smith run a program as jones on these machines: smith SAFE_HOSTS = (jones) /usr/local/bin/mycommand Let smith run all programs as jones on these machines: smith SAFE_HOSTS = (jones) ALL As an alternative, you can define a netgroup, in the /etc/netgroup file: safe-hosts (avocado,-,-) (banana,-,-) (cherry,-,-) Then use the netgroup in the /etc/sudoers file, with the "+" prefix: Host_Alias SAFE_HOSTS = +safe-hosts You can also use the netgroup in place of the host alias: smith +safe_hosts = (jones) ALL 5.6.3 Discussion This recipe assumes you have centralized your sudo configuration: the same sudoers file on all your computers. If not, you could grant per-machine privileges by installing a different sudoers file on each machine. Netgroups can be useful for centralization if they are implemented as a shared NIS database. In that case, you can update the machines in netgroups without changing your /etc/sudoers files. The host alias is optional but helpful for organizing your sudoers file, so you needn't retype the set of hostnames repeatedly. As another example, you could let users administer their own machines but not others: /etc/sudoers: bob bobs_machine = ALL gert gerts_machine = ALL ernie ernies_machine = ALL (Though this is perhaps pointless infrastructure, since ALL would permit these people to modify their /etc/ sudoers file and their root password.) ================================================================================================= Recipe 5.7 Granting Privileges to a Group via sudo 5.7.1 Problem Let a set of users run commands as another user. 5.7.2 Solution Define a Linux group containing those users: /etc/group: mygroup:x:1200:joe,jane,hiram,krishna Then create a sudo rule with the %groupname syntax: /etc/sudoers: # Let the group run a particular program: %mygroup ALL = (root) /usr/local/bin/mycommand arg1 arg2 # Give full superuser privileges to the group %mygroup ALL = (ALL) ALL ================================================================================================= Recipe 5.8 Running Any Program in a Directory via sudo 5.8.1 Problem Authorize a user to run all programs in a given directory, but only those programs, as another user. 5.8.2 Solution Specify a fully-qualified directory name instead of a command, ending it with a slash: /etc/sudoers: smith ALL = (root) /usr/local/bin/ smith$ sudo -u root /usr/local/bin/mycommand Authorized smith$ sudo -u root /usr/bin/emacs Rejected This authorization does not descend into subdirectories. smith$ sudo -u root /usr/local/bin/gnu/emacs Rejected ================================================================================================= Recipe 5.9 Prohibiting Command Arguments with sudo 5.9.1 Problem You want to permit a command to be run via sudo, but only without command-line arguments. 5.9.2 Solution Follow the program name with the single argument "" in /etc/sudoers: /etc/sudoers: smith ALL = (root) /usr/local/bin/mycommand "" smith$ sudo -u root mycommand a b c Rejected smith$ sudo -u root mycommand Authorized 5.9.3 Discussion If you specify no arguments to a command in /etc/sudoers, then by default any arguments are permitted. /etc/sudoers: smith ALL = (root) /usr/local/bin/mycommand smith$ sudo -u root mycommand a b c Authorized Use "" to prevent any runtime arguments from being authorized. ================================================================================================= Recipe 5.11 Permitting Read-Only Access to a Shared File via sudo 5.11.1 Problem Two or more users want to share a file, some read/write and the others read-only. 5.11.2 Solution Create two Linux groups, one for read/write and one for read-only users: /etc/group: readers:x:300:r1,r2,r3,r4 writers:x:301:w1,w2,w3 Permit the writers group to write the file via group permissions: $ chmod 660 shared_file $ chgrp writers shared_file Permit the readers group to read the file via sudo: /etc/sudoers: %readers ALL = (w1) /bin/cat /path/to/shared_file 5.11.3 Discussion This situation could arise in a university setting, for example, if a file must be writable by a group of teaching assistants but read-only to a group of students. If there were only two users—one reader and one writer—you could dispense with groups and simply let the reader access the file via sudo. If smith is the reader and jones the writer, and we give smith the following capability: /etc/sudoers: smith ALL = (jones) NOPASSWD: /bin/cat /home/jones/private.stuff then jones can protect her file: jones$ chmod 600 $HOME/private.stuff and smith can view it: smith$ sudo -u jones cat /home/jones/private.stuff ================================================================================================= Recipe 5.12 Authorizing Password Changes via sudo 5.12.1 Problem You want to permit a user to change the passwords of certain other users. 5.12.2 Solution To permit smith to change the passwords of jones, chu, and agarwal: /etc/sudoers: smith ALL = NOPASSWD: \ /usr/bin/passwd jones, \ /usr/bin/passwd chu, \ /usr/bin/passwd agarwal The NOPASSWD tag is optional, for convenience. [Recipe 5.4] 5.12.3 Discussion As another example, permit a professor to change passwords for her students, whose logins are student00, student01, student02,...up to student99. /etc/sudoers: prof ALL = NOPASSWD: /usr/bin/passwd student[0-9][0-9] Note that this uses shell-style wildcard expansion; see sudoers(5) for the full syntax. ================================================================================================= Recipe 5.13 Starting/Stopping Daemons via sudo 5.13.1 Problem You want specific non-superusers to start and stop system daemons. 5.13.2 Solution Here we let four different users start, stop, and restart web servers. The script for doing so is /etc/init.d/ httpd for Red Hat, or /etc/init.d/apache for SuSE. We'll reference the Red Hat script in our solution. /etc/sudoers: User_Alias FOLKS=barbara, l33t, jimmy, miroslav Cmnd_Alias DAEMONS=/etc/init.d/httpd start,\ /etc/init.d/httpd stop,\ /etc/init.d/httpd restart FOLKS ALL = (ALL) DAEMONS 5.13.3 Discussion Note our use of sudo aliases for the users and commands. Read the sudoers(5) manpage to learn all kinds of fun capabilities like this. ================================================================================================= Recipe 5.14 Restricting root's Abilities via sudo 5.14.1 Problem You want to let a user run all commands as root except for specific exceptions, such as su. 5.14.2 Solution Don't. Instead, list all the permissible commands explicitly in /etc/sudoers. Don't try the reverse—letting the user run all commands as root "except these few"—which is prohibitively difficult to do securely. 5.14.3 Discussion It's tempting to try excluding dangerous commands with the "!" syntax: /etc/sudoers: smith ALL = (root) !/usr/bin/su ... but this technique is fraught with problems. A savvy user can easily get around it by renaming the forbidden executables: smith$ ln -s /usr/bin/su gimmeroot smith$ sudo gimmeroot Instead, we recommend listing all acceptable commands individually, making sure that none have shell escapes. ================================================================================================= Recipe 5.15 Killing Processes via sudo 5.15.1 Problem Allow a user to kill a certain process but no others. 5.15.2 Solution Create a script that kills the process by looking up its PID dynamically and safely. Add the script to /etc/ sudoers. 5.15.3 Discussion Because we don't know a process's PID until runtime, we cannot solve this problem with /etc/sudoers alone, which is written before runtime. You need a script to deduce the PID for killing. For example, to let users restart sshd : #!/bin/sh pidfile=/var/run/sshd.pid sshd=/usr/sbin/sshd # sanity check that pid is numeric pid=`/usr/bin/perl -ne 'print if /^\d+$/; last;' $pidfile` if [ -z "$pid" ] then echo "$0: error: non-numeric pid $pid found in $pidfile" 1>&2 exit 1 fi # sanity check that pid is a running process if [ ! -d "/proc/$pid" ] then echo "$0: no such process" 1>&2 exit 1 fi # sanity check that pid is sshd if [ `readlink "/proc/$pid/exe"` != "$sshd" ] then echo "$0: error: attempt to kill non-sshd process" 1>&2 exit 1 fi kill -HUP "$pid" # /etc/sudoers: smith ALL = /usr/local/bin/sshd-restart "" The empty double-quotes prevent arguments from being passed to the script. [Recipe 5.9] Our script carefully signals only the parent sshd process, not its child processes for SSH sessions already in progress. If you prefer to kill all processes with a given name, use the pidof command: # kill -USR1 `pidof mycommand` or the skill command: # skill -USR1 mycommand ================================================================================================= Recipe 5.16 Listing sudo Invocations 5.16.1 Problem See a report of all unauthorized sudo attempts. 5.16.2 Solution Use logwatch: [Recipe 9.36] # logwatch --print --service sudo --range all smith => root ------------- /usr/bin/passwd root /bin/rm -f /etc/group /bin/chmod 4755 /bin/sh 5.16.3 Discussion If logwatch complains that the script /etc/log.d/scripts/services/sudo cannot be found, upgrade logwatch to the latest version. You could also view the log entries directly without logwatch, extracting the relevant information from /var/ log/secure: #!/bin/sh LOGFILE=/var/log/secure echo 'Unauthorized sudo attempts:' egrep 'sudo: .* : command not allowed' $LOGFILE \ | sed 's/^.* sudo: \([^ ][^ ]*\) .* ; USER=\([^ ][^ ]*\) ; COMMAND=\(.*\)$/\1 (\2): \3/' Output: Unauthorized sudo attempts: smith (root): /usr/bin/passwd root smith (root): /bin/rm -f /etc/group smith (root): /bin/chmod 4755 /bin/sh Recipe 5.17 Logging sudo Remotely 5.17.1 Problem You want your sudo logs kept off-host to prevent tampering or interference. 5.17.2 Solution Use syslog 's @otherhost syntax: [Recipe 9.29] /etc/syslog.conf: authpriv.* @securehost 5.17.3 Discussion Remember that the remote host's syslogd needs must be invoked with the -r flag to receive remote messages. Make sure your remote host doesn't share root privileges with the sudo host, or else this offhost logging is pointless. Update/HUP Syslog.conf on loghost(s) and clients Following is added on the loghost(s) ...;local2.info /var/adm/messages local2.info /var/adm/sudolog And here is what is added on all other machines local2.info /var/adm/sudolog local2.info @loghost local2.info @loghost2 ================================================================================================= Recipe 5.18 Sharing root Privileges via SSH 5.18.1 Problem You want to share superuser privileges with other users but not reveal the root password. 5.18.2 Solution Append users' public keys to ~root/.ssh/authorized_keys. In older versions of OpenSSH, the file for SSH-2 protocol keys is authorized_keys2. $ ssh -l root localhost or execute commands as root: $ ssh -l root localhost ...command... 5.18.3 Discussion As an alternative to su, you can use ssh to assign superuser privileges without giving out the root password. Users connect to localhost and authenticate by public key. (There's no sense using password authentication here: you'd have to give out the root password, which is exactly what we're trying to avoid.) This method is more flexible than using su, since you can easily instate and revoke root privileges: simply add and remove users' keys from ~root/.ssh/authorized_keys. However, it provides less logging than sudo: you can learn who became root (by log messages) but not what commands were run during the SSH session. Some discussion points: Make sure /etc/ssh/sshd_config has PermitRootLogin yes specified. ssh is built for networking, so of course you can extend the scope of these root privileges to remote machines the same way. Instead of connecting to localhost, users connect to the remote machine as root: $ ssh -l root remote_host Users can avoid passphrase prompts by running ssh-agent. [Recipe 6.9] This feature must be balanced against your security policy, however. If no passphrase is required for root privileges, then the user's terminal becomes a target for attack. For more security on a single machine, consider extending the method in this way: ================================================================================================= Recipe 5.19 Running root Commands via SSH 5.19.1 Problem You want to grant root privileges to another user, but permit only certain commands to be run. 5.19.2 Solution Share your root privileges via SSH [Recipe 5.18] and add forced commands to ~root/.ssh/authorized_keys. 5.19.3 Discussion Using SSH forced commands, you can limit which programs a user may run as root. For example, this key entry: ~root/.ssh/authorized_keys: command="/sbin/dump -0 /local/data" ssh-dss key... permits only the command /sbin/dump -0 /local/data to be run, on successful authentication. Each key is limited to one forced command, but if you make the command a shell script, you can restrict users to a specific set of programs after authentication. Suppose you write a script /usr/local/bin/ssh- switch: #!/bin/sh case "$1" in backups) # Perform level zero backups /sbin/dump -0 /local/data ;; messages) # View log messages /bin/cat /var/log/messages ;; settime) # Set the system time via ntp /usr/sbin/ntpdate timeserver.example.com ;; *) # Refuse anything else echo 'Permission denied' 1>&2 exit 1 ;; esac and make it a forced command: ~root/.ssh/authorized_keys: command="/usr/local/bin/ssh-switch $SSH_ORIGINAL_COMMAND" ssh-dss key... Then users can run selected commands as: $ ssh -l root localhost backups Runs dump $ ssh -l root localhost settime Runs ntpdate $ ssh -l root localhost cat /etc/passwd Not authorized: Permission denied Take care that your forced commands use full paths and have no shell escapes, and do not let the user modify authorized_keys. Here's a bad idea: ~root/.ssh/authorized_keys: DON'T DO THIS!!!! command="/usr/bin/less some_file" ssh-dss key... since less has a shell escape.