Blue background with illuminated circular lock with the Linux penguin and the word "Linux."

A caution about using sudo

The sudo program is an excellent way to extend “administrator”-like access to users who are not otherwise system administrators. In fact, modern Linux desktop distributions assume that at least one user should have an “administrator”-like role. When using a Linux system this way, a user can run certain “system” level commands as root, using their normal user account.

For example, on my Fedora Linux desktop system, I am this “administrator”-like person. I can run any command as root, simply by using the sudo command. I use this rarely, but it sometimes comes in handy. For example, while I can use a desktop package manager to install new programs and applications, I’m familiar enough with the Linux command line that I prefer to do it “by hand.” To install the pngcrush package, which can optimize a PNG graphic file for size, I just type this:

$ sudo dnf install pngcrush

Using sudo on a server

On a server where you need to provide other non-“administrators” with the ability to run certain commands as root, you can edit the /etc/sudoers file to specify who can run which commands. You can even limit the options that these users can give to these commands, such as only allowing certain users to mount the CD-ROM drive, as though they were root. The sudoers file contains examples of how to limit these kinds of commands.

But you need to be very careful about how you grant this access, and what commands they have access to run. Here’s an example that demonstrates what I mean:

A friend of mine used to work for a large company, as an applications administrator. Like many organizations, this company split up roles on the server: the systems administrators supported the hardware and operating system, the database administrators maintained the databases, and the application administrators ran the applications. The applications needed to be launched as root, so the systems administration team set up sudo commands for them.

For this example, let’s say the application was installed in /opt/___, which was “owned” by the application administrator team. Like good Linux users, the applications administrators set up scripts to automate tasks for them. For example, they had a script that acted like a “system” script, so they could start the application by running a command like /opt/___/bin/app with an option like start or stop or restart. You can imagine a script that looked like this: (I’ve replaced any actual commands with an echo command, because I’m only demonstrating it)

#!/bin/bash
# run this with 'sudo app start' or 'sudo app stop'

case "$1" in
start)
  echo 'starting app server..'
  ;;
stop)
  echo 'stopping app server..'
  ;;
restart)
  "$0" stop && "$0" start
  ;;
*)
  echo "usage: $(basename $0) start|stop|restart"
  ;;
esac

The system administrators set up an /etc/sudoers rule that allowed the application administrators to only run this script with start or stop or restart, with a rule that looked like this:

%apps ALL=/opt/___/bin/app start, /opt/___/bin/app stop, /opt/___/bin/app restart

With this rule, any member of the apps group (the application administrators) could start the application by typing this command:

$ sudo /opt/___/bin/app start
starting app server..

..or stop the application with this command:

$ sudo /opt/___/bin/app stop
stopping app server..

..or restart the application (such as when the application needs to be “refreshed”) by typing:

$ sudo /opt/___/bin/app restart
stopping app server..
starting app server..

A security issue

Using sudo made it easy to “draw a line” between the systems administrator and the application administrator roles. The applications team could manage the application without involving the systems team, especially because the applications team “owned” the /opt/___ directory on the server.

But do you see the security gap in this script? Here’s what happened:

One night, the application crashed hard. My friend was the application administrator on-call person, so he was paged by the automatic monitoring system. I don’t recall exactly what the problem was that night (it was years ago) but let’s say the issue was that the /opt filesystem had filled up. Through some investigation, my friend found that the “temporary” area in an unrelated /opt/temp directory was full. This directory was well known to only contain “interim” files, and deleting the files in this “temporary” area (especially file names starting with “tmp”) was safe to do.

But the system administrator on-call person wasn’t responding to calls. No one with the access to clean up the /opt/temp directory was available to do this quick task.

My friend realized they could run the script as root using sudo, and they could edit the script. So they made a quick edit to the /opt/___/bin/app script to clean up the /opt/temp directory. The edit might have looked like this: (again, I’ll use the echo command instead, because I’m only demonstrating it)

#!/bin/bash
# run this with 'sudo app start' or 'sudo app stop'

echo 'cd /opt/temp ; rm tmp.*'
exit

case "$1" in
start)
  echo 'starting app server..'
  ;;
stop)
  echo 'stopping app server..'
  ;;
restart)
  "$0" stop && "$0" start
  ;;
*)
  echo "usage: $(basename $0) start|stop|restart"
  ;;
esac

This modification to the script adds a command to delete temporary files in the /opt/temp directory, then immediately exit the script. With this edit, my friend ran the script with one of the options allowed in the /etc/sudoers rule file, such as stop, and the system cheerfully deleted the other temporary files:

$ sudo /opt/___/bin/app stop
cd /opt/temp ; rm tmp.*

After running this command, my friend removed the two extra lines from the script, returning things to normal.

Security and sudo

This demonstrates why it’s important to be careful about what commands you allow users to run with sudo. My friend was able to edit the script, so was effectively able to run any arbitrary command as root. Fortunately, this was a benign “abuse” of sudo, but imagine if a bad actor had been able to login as an application administrator and made a different change to the script–such as an edit that transferred system access to an outside agent. That would be a disaster.

This is not a sudo problem, but a user management issue. In fact, this issue is also noted in the sudo documentation, such as this note in the sudo(8) “man” page:

There is no easy way to prevent a user from gaining a root shell if that user is allowed to run arbitrary commands via sudo.

… Running shell scripts via sudo can expose the same kernel bugs that make set-user-ID shell scripts unsafe on some operating systems.

One way to avoid the problem I described is do not allow general users to edit the script. If the /opt/___/bin/app script were “owned” by root and mode 500 (that is, read+execute only by root) then the script could still be executable using sudo.

The sudo command is great for controlling access, but take this example as a general caveat about using sudo: you cannot let people edit any script that sudo lets them run.

Leave a Reply