Exploring sudoers

Linux server security is a vast topic. The first common steps are usually:

  • Disable SSH password and setup SSH key auth
  • Update the system regularly
  • Configure firewall
  • Disable root login
  • Change SSH port (security through obscurity for sure)

I may have missed a few. After that, the admin might go for:

  • Configuring users and file permissions
  • Using AppArmor and SELinux for locked down ACL
  • Hardening linux kernel (kicksecure comes to mind)
  • Stripping out any bloatware or unecessary services
  • Encrypting the disk with dm-crypt
  • Proper logging and monitoring

And much more. The list could go on and on. Today, I will be touching upon a small subset of it which is sudoers file.

Some background

What is a sudoers file? It’s main purpose is to restrict users from executing arbitrary commands. You can allow or disallow certain commands, file access, etc with it.

Think of it as a sudo policy which mandates who can run commands with sudo i.e. root permissions.

You can do a bunch of things with sudo. Such as monitor user activity. If a user is not allowed to run certain commands, it will be shown in the logs.

For example, user tau is trying to do something funny but we caught him in the logs!

tail /var/logs/auth.log | grep tau


Simple example

Alright, let’s start with a basic example. First, create a few users. You will need root privileges for creating users.

useradd john
useradd brock
useradd tau

Next, create a password for each of them

passwd john
passwd brock
passwd tau

Consider this scenario:

  • John is a sysadmin. He is allowed to execute all commands on all machines on the network and he can also execute it as another user.

  • Brock is a developer. He hates administration (just like every developer) and wants to run his go and python applications.

  • Tau is an intern. His current tasks involve monitoring the storage space and services using systemd. Nothing more.

A typical sudoers entry goes something like this:


Note: To edit a sudoers file, use sudo visudo instead of directly editing the file at /etc/sudoers. From the Arch Linux wiki:

It should always be edited with the visudo(8) command. visudo locks the sudoers file, saves edits to a temporary file, and checks it for syntax errors before copying it to /etc/sudoers.

For John we can enter:

john ALL=(ALL) ALL

For brock and tau, we have multiple services. Because of that, we have to setup aliases, just like a normal alias that you use in bash shell.

There are three types of aliases:

  • Host
  • User
  • Command

We will go with Command for now. Let’s create it for brock:

Cmnd_Alias DEVELOPER = /usr/bin/python3, /usr/bin/go

Same for tau:

Cmnd_Alias STORAGE = /usr/sbin/fdisk, /usr/bin/du, /usr/bin/systemctl start,
/usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart,
/usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/bin/systemctl disable


We are set here. Let’s test it.

Switching to user john and running update command:

su john
sudo apt update -y


You can perform anything from editing hosts file to checking open ports with lsof.

Let’s switch to brock and run the update command again.

su brock
sudo apt update -y


Permission denied. As expected. Can we run the commands that we are allowed to?

Brock is allowed to execute /usr/bin/python3 and /usr/bin/go.

We can’t create a python file here because of lack of permissions. However, for now, we can switch to /tmp directory which has rwx permissions for all users.

cd /tmp
echo "print(\"hello\")" > hello.py
python3 hello.py


Similarly, try executing go commands. It should work as intended.

Our last user is tau. Perform the same operations as we did on brock.

su tau

Let’s run the systemctl command which we are allowed to:

sudo systemctl status sshd


What? I thought tau was allowed to do that.

Yes. But you see, sudo is very strict when we give subcommands of a command.

In the previous rules, we just provided a single command and therefore you can execute all of it’s subcommands.

But when you provide a command along with it’s subcommand, that’s all you can execute. It doesn’t let you execute subcommands of a subcommand.

systemctl status or systemctl start is quite useless without specifying the actual service. To allow that, we can use * wildcard. Let’s edit the policy for STORAGE:

Cmnd_Alias STORAGE = /usr/sbin/fdisk, /usr/bin/du, /usr/bin/systemctl start *,
/usr/bin/systemctl stop *, /usr/bin/systemctl reload *,
/usr/bin/systemctl restart *, /usr/bin/systemctl status *,
/usr/bin/systemctl enable *, /usr/bin/systemctl disable *

Save it and then try running the status for a service:

sudo systemctl status sshd


Sweet! We haven’t covered the other two aliases but they basically work the same way. For host, use Host_Alias and for user, User_Alias.

Let’s say you want to add another admin or a developer. Instead of creating a new rule, just create an alias and then use that alias in the username field:

User_Alias ADMINS = john, jack
Host_Alias HOST = prod, test


There’s still a lot more to a sudoers file. I will try to cover it in another part of the blog post.

Keep experimenting!