..

Exploring sudoers

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

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

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

auth


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:

A typical sudoers entry goes something like this:

sudo

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:

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

Cmnd_Alias DEVELOPER = /usr/bin/python3, /usr/bin/go
brock ALL=(ALL) DEVELOPER

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

tau ALL=(ALL) STORAGE

We are set here. Let’s test it.

Switching to user john and running update command:

su john
sudo apt update -y

update

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

brock

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

hello

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

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

ssh

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

ADMINS HOST=(ALL) ALL

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!