The root password can be a cause of contention in any organization . Many system administrators hate giving it out, even to people who are responsible for maintaining part of the system. If this sort of system administrator doesn't know how to properly manage things, this reluctance can keep people from being able to do their jobs. Many other system administrators hand out root to dang near anyone who wants to use it, and then complain when the system becomes unstable.
by Michael W. Lucas
Using Groups
Unix has powerful facilities for removing the need to use the root password. In the next few articles, we're going to consider minimizing use of the root password.One common situation is where a junior administrator is responsible for a particular portion of the system. i.e DNS administrators;
these people don't ever install software, recompile the kernel, or do other low-level system tasks. They just answer email, update the zone files on the nameservers, and reload
named
.New junior administrators frequently seem to think that they need root to do this sort of work. With proper use of groups, and a bit of scheduling, you don't need to hand out root at all! Here, we're going to implement group-based security for managing DNS files. The same techniques can be applied to almost any other section of the system.
Unix classifies users into groups, each group consisting of people who perform similar administrative functions. You can have a group called
Web
, which includes the people who edit Web pages, and a group called dns
that includes the people who manage your nameserver. Depending on your operating system, you might already have groups with similar names.For example, NetBSD and OpenBSD both include a user and a groupThese predefined users and groups are generally used by programs on the system. Web servers generally run as thenamed
, while FreeBSD has a user and group calledbind
, all for use by the nameserver.
www
user, for example.For our purposes, we'll want to define a separate group for users who need access to files used by these programs. We don't need a matching user account, however. Group information is in
/etc/group
. Each line in /etc/group
contains four colon-delimited fields.- The first is the group name. Group names are fairly arbitrary: you could give your DNS managers the group name "losers" if you wished. It's a good idea, however, to choose group names that give you some idea of what they're for; while you might remember that the group xyzzy manages your email system today, will you remember it six months from now? Choose group names that mean something.
- The second field contains the group's encrypted password. Group passwords encouraged poor security practices, so most modern Unixes don't support them. As with many other things in Unix, however, this field has always been there and so we're stuck with it. Rather than leave this field blank, we use an asterisk (*) as a placeholder.
- The third field holds the group's unique numeric ID (GID). Many of FreeBSD's internal programs use this GID, rather than names, to identify groups.
/etc/groups
is sorted in order by GID. - Last is a list of all the users in that group. To add a user to a group, simply add the username to this list, separated from other names with commas.
dns
group we're creating, which are closely related to another group in the system, I'll frequently pick a GID that's off by one from its related group.For example, on FreeBSD the bind user has a GID of 53 (from the network port number nameservers use). Our new
dns
group will have a GID of 54. I want to add the local users "chris", "phil", and "michael" to this group, so our new entry will look like this.After editingdns:*:54:chris,phil,michael
/etc/group
, it's a good idea to make sure you haven't made a mistake. FreeBSD includes chkgrp(8)
, which checks the syntax of the groups file; if it runs silently, you haven't shot yourself in the foot.Now that you have a group, you can use it to assign ownership of files. Every file is owned by both a user and a group. You can see the existing ownership of a file with
ls -l
. Many new system administrators pay close attention to the owner, and to the word permissions, but gloss over the group permissions.# ls -l
total 29
-rw------- 1 root wheel 27136 Sep 14 09:36 file1
-rwxrwxr-- 1 root wheel 1188 Sep 14 09:35 file2
Here, file1
can only be read or written to by root. file2
can be read by root or any member of the group wheel. If you're in the wheel group, you don't need to become root to edit or read file2
file; you can just open your text editor and go!To change a group owner on a file, use
chgrp(1)
# chgrp groupname filename
Now, in BSD wheel
is a system group. Wheel
is the group of users who may use the root password. You don't want to go generically making files writable by wheel
; this would strongly violate the principle of least privilege.Similarly,
bind
is a group used by the nameserver program. You don't want the nameserver program to be able to write DNS zone files; if someone compromises the nameserver, then the nameserver would be able to write files directly to the disk. This would be bad. But consider the following permissions scheme on the zone file for blackhelicopters.org:This file is owned by me, as the senior administrator, but it's writeable by anyone in the-rw-rw-r-- 1 mwlucas dns 486 Jun 7 10:14 blackhelicopters.org.db
dns
group. (You could also set up a particular user to own these files.) Anyone in the dns
group can read and write to this file, without using the root password. Finally, this file can be read by the nameserver.The only thing the DNS administrators need the root password for now is to restart the nameserver. This is easily dealt with by setting up a cron job to reload the nameserver. These administrators still might want to reload the nameserver manually on occasion, however. We'll look at allowing them to do so without using the root password in the next article....
Using sudo
While proper implementation of groups can help reduce the need for the root password, at times, users must absolutely run commands as another user (usually root). As the system administrator, you're stuck between deciding to hand out the root password or doing everything for your users.
sudo
provides a third way, one that can help solve this dilemma. It's a tricky program, however, and needs some care in implementation. sudo
is integrated into OpenBSD, and is an add-on package for just about every other Unix-like operating system out there.sudo
is a setuid root wrapper that implements fine-grained access control for commands that need to be run as root. It takes the command you want to run and compares it to its internal list of permissions. If sudo
's permissions allow that particular user to run that command, sudo
runs that command for you, with its privileges. As root can run commands as any user, sudo
can execute commands as any arbitrary system user.With proper setup, the system administrator can allow any user to run any command as any other user.
sudo
is a very powerful tool, and can be configured to allow or deny almost any set of commands. As a result of this flexibility, the documentation tends to scare off new users.
We're going to do a basic sudo
setup that will cover almost all uses, but you should be aware that many more combinations are possible, and are documented in sudo(8)
and sudoers(5)
.Other than the obvious fine-grained access control
sudo
provides, there are a few other benefits to using sudo
.- One of the biggest advantages is the command logging. Every
sudo
command is logged, making it very easy to track who made what changes. - And once you have
sudo
configured correctly, you can change the root password and not give it to anyone. Nobody should need the root password if they have the correctsudo
permissions, after all! Reducing the number of people who have the root password can help improve security. - Finally, a single
sudo
configuration file can be used on all of these systems, vastly easing administrator overhead.
sudo
is that users and junior administrators don't like it. If people have traditionally had root access on a system, they will perceive that they're losing something when you implement sudo
.The key to overcoming this is to make sure that people have the ability to do their jobs. If users think that they need the root password to perform other tasks, then your need to settle just who is responsible for what. These users may have been taking extra duties upon themselves, rather than troubling you with jobs that you should do.
A faulty
sudo
setup can create security holes. A thoughtless configuration will create holes in the system that a clever user can use to actually become root. This problem is best dealt with by a combination of careful configuration and administrative policy. sudo
has three pieces.- The first is the actual
sudo(8)
command, the setuid root wrapper that users will actually use. - There's also
sudo
's configuration file,/etc/sudoers
. This file issudo
's permissions table, saying who may run what commands as which user, and is fully documented insudoers(5)
. - Finally, the
visudo(8)
command allows administrators to edit thesudoers
file without risking locking themselves out of the system.
visudo
, the sudoers file
, and sudo
itself.If the syntax in yourMuch likesudoers
file is incorrect,sudo
will not run. If you're relying onsudo
to provide access to thesudoers
file, and you corrupt thesudoers
file, you can lock yourself out of root-level activities on the system and be unable to correct your error. This is bad.visudo(8)
provides some protection against this sort of error.
vipw(8)
, visudo(8)
locks the file so only one person can edit the configuration file at a time. It then opens the sudo
configuration file in an editor (vi(1)
by default, but it respects the $EDITOR
environment variable).When you exit the editor,
visudo
parses the file and confirms that there are no sudo
syntax errors (This is not a guarantee that the configuration will do what you want, merely a confirmation that the file is actually a valid). visudo(8)
will accept a configuration file that says "nobody may do anything via sudo
" if the rules are properly formatted.If
visudo
finds an error when you exit the editor, it will print out the line number and ask you what you want to do:# visudo >>> sudoers file: syntax error, line 44 <<< What now?
Here, we've made an error on line 44. You have three choices:- edit the file again,
- quit without saving any of the changes you made, or
- forcing
visudo
to write thesudoers
file you created.
visudo
will send you back to the editor. You can go to the line it complained about, and try to find your error.If you enter x,
visudo
will quit and revert the configuration file to what it was before you started editing. Your changes will be lost, but that may be all right. It's better to have the old, working configuration, than have a new, non-functional configuration.Entering Q forces
visudo
to accept the file, syntax error and all. If your configuration file has an error, sudo
will not run. Essentially, you're telling visudo
to break sudo
until such time as you log in as root to fix the problem. This is almost certainly not what you want to do!The
sudoers
file tells sudo
who may run which commands as which users. OpenBSD stores the sudoers
file as /etc/sudoers
, FreeBSD stores it as /usr/local/etc/sudoers
. Never edit this file directly, even if you think you know exactly what change you want to make; always use
visudo(8)
.The
sudo
permissions syntax can be confusing until you understand it. Getting everything correct can be difficult the first time. Once you understand how sudo
sets things up, however, it's very quick and easy.The various sample
sudoers
files you'll find on the Internet frequently look quite complicated and difficult to understand, as they demonstrate all the nifty things you can do with sudo
. The basic syntax is very simple. Each rule entry in sudoers
has the following format:username host = command
- The
username
is the username of the user who may execute the command. host
is the hostname of the system where this rule applies.- The
command
field lists the commands this rule applies to. You must have a full path to each command name, orsudo
will not recognize it! (You wouldn't want people to be able to adjust their$PATH
variable to access renamed versions of commands, now would you?)
sudo
is designed so you can use one sudoers
file on all of your systems. This space allows you to set per-host rules. sudo
defaults to not allowing anything to happen. To let a user run a command, you must create a rule that gives that user permission on that host to run that command. If any of the three fields don't match, the user cannot run the command.You can use the
ALL
keyword in any of these fields to match all possible options. For example, suppose I trust user "chris" to run absolutely any command as root, on any system:chris ALL = ALL
Giving a junior system administrator total control of one of my systems isn't very likely. As senior system administrator, I should know what commands Chris needs to run to do his job. Suppose Chris is in charge of the nameserver portion of this system. We control actual editing of the zone files with group permissions, but that won't help when the nameserver must be started, reloaded, or stopped. Here, I'll give him permission to run just the name daemon controller program, ndc(8)
.chris ALL = /usr/sbin/ndc
If I'm sharing this file across several machines, it's quite probable that many of those machines are not even running a nameserver program. Here, I'll restrict which machine Chris may run this program on to the server called "dns1
."chris dns1 = /usr/sbin/ndc
On the other hand, Chris is the administrator of the email server "mail
". This server is his responsibility, and he can run any commands on it whatsoever. I can set entirely different permissions for him on the mail server, and yet use the same sudoers
file on both the systems.You can specify multiple entries in a single field by separating them with commas. Here, I'd like Chris to be able to mount floppy disks withchris dns1 = /usr/sbin/ndc
chris mail = ALL
mount(8)
, as well as control the nameserver.chris dns1 = /usr/sbin/ndc, /bin/mount
You can tell sudoers
that a user can run commands as a particular user, instead of root, by putting the username in parenthesis before a command. For example, suppose we have our nameserver set to run as the user "named
" and all commands to control the server must be run as that user:chris dns1 = (named) /usr/sbin/ndc
Every entry in /etc/sudoers
must be on a single line. This can make the lines very long. If you have a long list of alias members or rules, you can skip to another line by using the \
character at the end of each incomplete line.Now that you understand howchris server1 = /sbin/fdisk,/sbin/fsck,/sbin/kldload,\
/sbin/newfs,/sbin/newfs_msdos,/sbin/mount
sudo
permissions are set, let's look at how to actually use sudo
. Use visudo
, and give your account privileges to run any command. (If you've installed sudo
correctly you already have root, so this won't be a security issue.)The first time you run
sudo
, sudo
will prompt you for a password.Enter the password for your own account, not the root password.If you give an incorrect password,
sudo
will insult your typing abilities, mental facilities, or ancestry, and let you try again. After three incorrect passwords, sudo
gives up on you. You'll have to re-enter the command you want to run.Once you enter a correct password,This makes work easier when you're issuing a series of commands undersudo
records the time. If you runsudo
again within five minutes, it won't ask you for a password. After you don't usesudo
for five minutes, however, you must re-authenticate.
sudo
, but times things out quickly in case you walk away from the computer.When you're a regular user on a system with
sudo
, one thing you'll probably want to know is what commands the system administrator has permitted you to run. sudo
's -l
flag will tell you this.If you had tighter restrictions, they would be displayed.# sudo -l Password: User mwlucas may run the following commands on this host: (root) ALL
To run commands via
sudo
, just put the word "sudo
" before the command you actually want to run. For example, here's how we would become root using su
via sudo
.# sudo su Password: #
Using sudo
to become root simply allows the senior system administrator keep the root password a closely-held secret.This isn't entirely useful, as with unrestricted sudo
access junior administrators can change the root password.
Still, it's a start towards keeping the system more secure, and towards implementing sudo
for all commands.You can run more complicated commands under
sudo
, with all of their regular arguments. For example, tail -f
is excellent to view the end of a log file, and to have new log entries appear on the end of the screen. Some log files are only visible to root, or should be -- for example, the log that contains sudo
use information. You might want to view these logs without bothering to become root.# sudo tail -f /var/log/authlog
openbsd/usr/src/usr.bin/sudo;sudo tail -f /var/log/secure
Jul 29 13:24:19 openbsd sudo: mwlucas : TTY=ttyp0 ; PWD=/home/mwlucas ;
USER=root ; COMMAND=list
Jul 29 13:30:03 openbsd sudo: mwlucas : TTY=ttyp0 ; PWD=/home/mwlucas ;
USER=root ; COMMAND=/usr/bin/tail -f /var/log/authlog
...
You can choose to run commands as a user other than root, if you have the appropriate permissions. For example, suppose we have our database application where commands must be run as the database user. You tell
sudo
to run as a particular user by using the -u
flag and a username. For example, the operator user has the privileges necessary to run dump
and back up the system.# sudo -u operator dump /dev/sd0s1
All this tracking and accountability is nice, but where does it account to? sudo
messages are logged. Each log message contains a timestamp, the name of the user, the directory where sudo
was run, and the command that was run.Jul 29 11:21:02 openbsd sudo: chris : TTY=ttyp0 ; PWD=/home/chris ; USER=root ; COMMAND=/sbin/mount /dev/fd0 /mnt
In the worst case, you can backtrack exactly what happened when something breaks. For example, if one of my systems doesn't reboot correctly because /etc/rc.conf
is missing or corrupt, I can check the sudo
logs to who touched it.Jul 29 11:34:56 openbsd sudo: chris : TTY=ttyp0 ; PWD=/home/chris ; USER=root ; COMMAND=/bin/rm /etc/rc.conf
If everyone had been usingsu
, or even using "sudo su
" instead ofsudo
to run each individual command, I would have had no clue as to why the system broke. Withsudo
logs, once I get this computer up and running again I know who to blame. This alone makessudo
worth implementing.
No comments:
Post a Comment