16.3. Becoming a Superuser with the su Command
The su (switch user) command allows you to become another user without logging off. The su command can take as its argument the name of another user, and if you know that user's password, a new shell will be started owned by the username you specified, allowing you to gain the privileges of that user temporarily. If you do not specify a username, the su command defaults to root, and will ask for a password. If you use a dash (–) option after the su command (with or without the username), the new shell will inherit the environment of the specified user, including variables such as SHELL, HOME, and PATH.
Traditionally, when a system administrator wants to run some commands that require root privileges, he or she logs onto an unprivileged account first, and then uses the su command to switch to superuser. A new root-owned shell will be started, and after running privileged commands (presumably to fix a problem that the user can't handle), the superuser will exit from the root shell and return to the account of the unprivileged user.
Example 16.2.
1 $ id # or use whoami instead
uid=501(ellie) gid=100(users) groups=100(users)
2 $ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:.
3 $ su
Password:
4 # id
uid=0(root) gid=0(root) groups=0(root)
5 # echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:.
6 # exit
exit
7 $ su -
Password:
8 # id
uid=0(root) gid=0(root) groups=0(root)
9 # echo $PATH
/usr/sbin:/bin:/usr/bin:/sbin:/usr/X11R6/bin
EXPLANATION
The id command shows that ellie is the current user. The PATH variable for user ellie is displayed. The su command is run to switch user to root. Note that a password must be provided. The prompt has changed to a pound sign (#). This almost always signifies a superuser account. The id command is run, showing that the current shell has root permissions. When the value of the PATH variable is displayed, it shows the same value as before. This is because the plain su command (without the dash) was used to become root. Plain su does not change the value of the PATH variable. Exit is run to terminate the shell created by the su command. The prompt changes back to a dollar sign because the previous command terminated the root-owned shell. The su command is run, this time including the dash option. The id command verifies that root is the current user. Because this shell was run using the dash option to the su command, the PATH value from the root account was used. When the value of the PATH variable is echoed, it shows root's path.
If you use the su command to gain root privileges, you should use the dash (–) option to obtain the root environment, especially the root PATH. The example below shows the su command being run with and without the dash option. Notice that without the dash, the wrong version of the useradd command is run.
Example 16.3.
1 $ id
uid=501(ellie) gid=100(users) groups=100(users)
2 $ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:.
3 $ su
password:
4 # echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:.
5 # cd /tmp
6 # ls -l useradd
-rwxr-xr-x 1 ellie group 65 Feb 12 11:56 useradd
7 # ls -l /usr/sbin/useradd
-rwxr-xr-x 1 root root 57348 Mar 17 2003
/usr/sbin/useradd
8 # useradd newguy
this is the useradd script in the /tmp directory
9 # tail -1 /etc/passwd
ellie:x:501:100::/home/ellie:/bin/bash
# exit
10 $ su -
password:
11 # useradd newguy
12 # tail -1 /etc/passwd
newguy:x:502:100::/home/newguy:/bin/bash
13 # exit
EXPLANATION
The id command is run and shows that this shell is owned by the user ellie, a non-superuser account. The PATH variable is displayed, showing that it does contain the . directory but does not contain the /usr/sbin directory. The su command is run, starting a new shell owned by root. The PATH variable is displayed, showing that it has not changed. The cd command is run to make /tmp the current directory. The ls command shows that a program called useradd exists in the current directory, which is the /tmp directory. This program will almost certainly not exist on your system. This program happens to be in the /tmp directory on this particular system. This ls command shows that there is also a useradd program in the /usr/sbin directory. The version in /usr/sbin is the normal useradd command that the administrator uses to create a new account. The useradd command is run. The shell runs the copy of useradd in the current directory because of the . (dot) in the PATH. This was not the intention; the useradd command from the /usr/sbin directory was meant to be run instead. As a result of this error, the newguy account was never added. The current root-owned shell is terminated with the exit command. The su command is run again, this time using the dash option. The su command will use root's PATH instead of the PATH from the nonprivileged account when it creates the new shell (the shell created by the su command). The useradd command is executed again. The shell will use root's PATH to find the command, and useradd from the /usr/sbin directory will be executed. The useradd command will add a new line to the end of the /etc/passwd file to create this account. The tail command is used to display the last line of the /etc/passwd file. You can see that the newguy account has been added. The root-owned shell is exited. This is a good practice—root shells should be terminated when the superuser has finished running commands that require root access. If the superuser forgets to exit the root shell, it is wide open to anyone who uses the account. Not a good idea!
16.3.1 Running Scripts As Root
Running a script from a root account (superuser) requires a slightly different technique than running a script as a regular user. Traditionally, root accounts have a different value for the PATH variable than that in nonprivileged accounts. The PATH for root usually consists of directories containing system commands. For example, the /usr/sbin directory is usually part of root's PATH, but not part of the PATH for a nonroot account. In order to prevent root from accidentally running a program in the current directory, root's PATH variable does not usually contain the current directory, called the dot directory and represented by a period.
Running a Script in the Current Directory
Because the . (dot) is not part of root's PATH, scripts will not run when invoked in the normal manner by typing the script name by itself at the command line. When you run a script as root, you should precede the script with the name of the invoking shell.
Example 16.4.
1 # cat myscript
#! /bin/sh
echo this is my script
2 # echo $PATH
/usr/sbin:/bin:/usr/bin:/sbin:/usr/X11R6/bin
3 # myscript
bash: myscript: command not found
4 # /bin/sh myscript
EXPLANATION
The contents of the shell script, myscript, are displayed. The first line of this script indicates that it was written for the /bin/sh program, which is the Bourne shell. The value of the PATH variable is displayed. Notice that the PATH does not contain the dot (.) directory. This command fails because the PATH does not include the . (dot) directory. This command succeeds because the script name is passed as an argument to the shell, /bin/sh. By invoking the shell in this way, the PATH variable is not used to locate the script; instead the shell will check the current working directory to see if the script is there.
Another way to execute a script or any other command in the current working directory is to precede the program with a ./ to indicate that the program is in the current working directory.
Example 16.5.
1 # cd /usr/local/bin
2 # myprog
-bash: myprog: command not found
3 # ./myprog
this is my program
EXPLANATION
The current directory is changed to /usr/local/bin. This directory contains a program called myprog. An attempt to run the program, myprog, does not succeed. Without a . in the PATH, the shell cannot locate the program. After specifying the location of myprog (the . directory), the command runs successfully.
16.3.2 Scripts That Run As Root (setuid Programs)
Whoever runs a setuid program temporarily becomes the owner of that program and has the same permissions as the owner. Although most setuid programs are set to root, they can be set to any user. If a setuid program is set to root, when an unprivileged user runs such a program, he or she temporarily becomes root. This is kind of a Cinderella story because when the program exits, the user goes back to his or her lowly station in life and loses all root privileges. The passwd program is a good example of a setuid program. When you change your password, you temporarily become root, but only during the execution of the passwd program. That is why you are able to change your password without going to a system administrator for help. If you couldn't run as root, you would not be allowed to access the /etc/passwd (or /etc/shadow) file, which normally is off-limits to regular users. To identify a setuid program, use the ls –l command. The x (execute) permission will be replaced with an s if the program is a setuid program.
Example 16.6.
1 $ ls -l /bin/passwd
-r-sr-sr-x 1 root sys 21964 Apr 6 2002 /bin/passwd
2 $ ls -l /etc/shadow
-r-------- 1 root sys 4775 May 5 13:33 /etc/shadow
EXPLANATION
The output of ls –l shows that this setuid program will run as root. The letter s replaces the x (execution bit) in the permissions field. The /etc/shadow file, where passwords are stored (Solaris), shows that this is a root-owned file, and only root can read it.
Shell programs can be written as setuid programs and are a serious security threat if they are not monitored by a system administrator. If a shell script is a setuid program (to root), the shell spawned is a root-owned shell and commands executed from the script are run as root. Why would a shell script need to be a setuid program? If a file such as a database or log file contains information that should not be accessible to regular users, the permissions on that file should be turned off for everyone except the owner. If a script needs to access the file, and it is executed by a nonprivileged user, the error Permission denied will be displayed and the script will fail. If the script is a setuid script, the person running the script can take on the identity of the owner of the file and get access to the data in the file. Not all shells allow scripts setuid to root permission, and even if the shell allows it, the operating system may not. For example, Bash does not support setuid scripts, whereas Korn shell has a privileged mode (–p) used to run setuid scripts, only if allowed by the operating system. The following steps set up a setuid program for a C/TC shell script.
- 1. In the script, the first line is
#!/bin/csh –feb
The –feb options:
–f fast start up; don't execute .cshrc –e abort immediately if interrupted –b this is a setuid script
- 2. Next, change the permissions on the script so that it can run as a setuid program:
% chmod 4755 script_name
or
% chmod +srx script_name
% ls –l
–rwsr–xr–x 2 ellie 512 Oct 10 17:18 script_name
Because of the security risks involved with setuid programs, most systems will allow the administrator to disable setuid and setgid programs for individual filesytems. The UNIX find command can also be used to locate programs that are setuid to root:
# find / -user root -perm -4000 | more
Within a shell script, you can check for files that are setuid programs with the file-testing operators available for all shells. For example, Korn and Bash shells, the test would be:
if [[ -u filename ]] ; then
for C/TC shell:
if { test -u filename } then
and for Bourne shell:
if test -u filename; then
or
if [ -u filename ]; then
|