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
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
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
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
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
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!