It has been possible to use wildcards in the sudoers file for many years. This can make configuration easier and more flexible, but it also introduces problems of its own. Regular expressions, introduced in in sudo 1.9.10, allow you to create more fine grained rules. From this blog you will learn about some of the problems when you use wildcards in your sudoers file, and how using regular expressions can resolve those problems.
To use regular expressions in your sudoers file you need at least sudo version 1.9.10 on your system. Most operating systems still use an earlier version. Compiling sudo is easy, but it is even easier to use a ready-to-use binary. Packages for many operating systems are available on the sudo website at https://www.sudo.ws/getting/packages/.
Let’s start with a simple example: giving access to log messages to some of the users using sudo. In theory it is really simple:
czanik ALL = /bin/cat /var/log/*
In practice this has some unwanted side effects, as ‘*’ will match any characters, including white space:
czanik@slack:~$ sudo cat /var/log/secure /etc/shadow [...] nobody:*:9797:0::::: ldap:*:9797:0::::: czanik:$6$zGV6MOIF9ZHmlpyB$MwoDkqWxEdQ.GOQzpm6MaSAtZwuY/.0iVIRM8cGZWt1uI6wRw5ZmxGfCpj4PMIpKVyQP2NiwZ7grCz7ZQuLXK0:19053:0:99999:7:::
The sudoers rule gives read access to any file on the system, including ones containing sensitive information which the user does not have permission to read by default.
When using regular expressions, it is easier to properly limit what a user can do:
czanik ALL = /usr/bin/cat ^/var/log/[a-zA-Z0-9]+$
The sudoers file marks regular expressions with a ‘^’ at the beginning and a ‘$’ sign at the end. In between you can use regular expressions instead of wildcards to describe access. In this case the file name must be one or more characters long, and can include only letters and numbers. Adding a second file name or using dots in the path name will deny access:
czanik@czplaptop:~> sudo cat /var/log/messages /etc/shadow Sorry, user czanik is not allowed to execute '/usr/bin/cat /var/log/messages /etc/shadow' as root on czplaptop. czanik@czplaptop:~> sudo cat /var/log/../../../../etc/shadow czanik's password: Sorry, user czanik is not allowed to execute '/usr/bin/cat /var/log/../../../../etc/shadow' as root on czplaptop.
That looks a lot better :-)
Root does not have always time to handle password problems, so let’s delegate it:
czanik ALL = /usr/bin/passwd [a-zA-Z0-9_]*, !/usr/bin/passwd root
Now my user can change the password of any user on the host, but not the one belonging to root. With the requirement that the user name is at least one character long, the user cannot play the trick of not giving a user name and starting the passwd command as root. So, we are safe:
czanik@slack:~$ sudo passwd root Password: Sorry, user czanik is not allowed to execute '/usr/bin/passwd root' as root on slack.example.org. czanik@slack:~$ sudo passwd bla Password: passwd: user 'bla' does not exist czanik@slack:~$ sudo passwd Sorry, user czanik is not allowed to execute '/usr/bin/passwd' as root on slack.example.org.
Or, are we? Changing the root password is explicitly disabled. However, the * wildcard allows any number of characters, including white space and dash, which is used for command line arguments:
czanik@slack:~$ sudo passwd root -l passwd: password expiry information changed. czanik@slack:~$ sudo passwd root -u passwd: password expiry information changed.
Even without changing the root password, it is possible to cause some difficult moments for the root user. Using regular expressions you can fine tune the rule making sure that command line arguments cannot be used:
czanik ALL = /usr/bin/passwd ^[a-zA-Z0-9_]+$, !/usr/bin/passwd root
Like many other sysadmins, I do not like regular expressions. It is easy to write difficult to debug expressions, which you may not understand later (or even the next day). However, using simple wildcards can easily give more permissions to your users than intended. So, refresh your memories about regular expressions and fine tune rules on your hosts using sudo 1.9.10.
If you would like to be notified about new posts and sudo news, sign up for the sudo blog announcement mailing list.