As Linux administrators we have become used to the proliferation of SUID bits that we set on our systems. As long as the list of programs that have these permissions set does not change, then we don’t worry too much. However this is still a dangerous strategy as any program that has the SUID bit will be running as root. More often than not, they need a small subset of permissions and this is where capabilities come into play. These capabilities have been included in Linux kernel for many years now. Version 2.2 saw their introduction and 2.6 took it a step further where capabilities can be assigned to executable files. It is these we will look at in this module.
We will use Ubuntu 18.04 and CentOS 7 for the demonstration, both are recent distributions and we will see that CentOS makes use of the capabilities for the ping program and Ubuntu does not, relying on the use of the SUID bit.
Replacing the SUID Bit with POSIX Capabilities
On both systems the ping will work for standard users but on CentOS 7 the rights are assigned through limited capabilities rather than running as root. We can see this on CentOS 7 by looking at the capabilities of the the ping executable and the permissions assigned.
$ ls -l /bin/ping ; getcap /bin/ping -rwxr-xr-x. 1 root root 66176 Aug 4 2017 /bin/ping /bin/ping = cap_net_admin,cap_net_raw+p
It is the command getcap that can return a list of capabilities assigned to an executable file. We see here that there are two capabilities assigned to permit. I would argue that only cap_net_raw is required and cap_net_admin isn’t required for standard ping use. To review all that is assigned with these capabilities visit the man pages using
$ man 7 capabilities
When we review the same on the Ubuntu 18.04 system we see there are no capabilities set and the SUID permission is set on the file meaning that it will run as the file’s owner, root.
$ ls -l /bin/ping ; getcap /bin/ping -rwsr-xr-x 1 root root 64424 Mar 9 2017 /bin/ping
First we will remove the SUID permission and test ping as a standard user, the ping will fail:
$ sudo chmod 755 /bin/ping $ ls -l /bin/ping -rwxr-xr-x 1 root root 64424 Mar 9 2017 /bin/ping $ ping localhost ping: socket: Operation not permitted
So these are the same permissions as on CentOS 7 but without the capability in place. We will now add the capability, just CAP_NET_RAW:
$ sudo setcap CAP_NET_RAW=p /bin/ping $ getcap /bin/ping /bin/ping = cap_net_raw+p $ ping localhost PING localhost (127.0.0.1) 56(84) bytes of data. 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.028 ms CTRL+C
We have applied just the rights that the program needs and have avoided using full root privileges ; albeit slightly, we have helped secure or Linux system.
If we want to list all of the capabilities we have in the Kernel then review the man page. To list just the capabilities try this:
$ man capabilities | grep -E '^\s{7}CAP_' CAP_AUDIT_CONTROL (since Linux 2.6.11) CAP_AUDIT_READ (since Linux 3.16) CAP_AUDIT_WRITE (since Linux 2.6.11) CAP_BLOCK_SUSPEND (since Linux 3.5) CAP_CHOWN
The video follows: