Linux capability-based security

From SkullSpace Wiki
Jump to navigation Jump to search


Background

Capability-based security is basically the idea that instead of requiring a user be given root access to do certain tasks they need to do, they are instead given the capability to do those tasks without involving root at all. This can be built in to any modern Linux kernel (since kernel 2.2) and is the preferred method of giving normal users the ability to perform tasks that have historically required sudo or setuid root. The problem with setuid root and sudo is that this can lead to privilege escalation and the execution of arbitrary commands as the root user if it is not done carefully (and sometimes even when it is).

List of capabilities in Linux

Here's some of the most useful capabilities in Linux:

CAP_CHOWN Make arbitrary changes to file UIDs and GIDs.
CAP_NET_ADMIN Perform various network-related operations.
CAP_NET_BIND_SERVICE Bind a socket to Internet domain privileged ports (port numbers less than 1024).
CAP_NET_RAW Use RAW and PACKET sockets.
CAP_SYS_MODULE Load and unload kernel modules.
CAP_KILL Bypass permission checks for sending signals.
CAP_DAC_OVERRIDE Bypass file read, write, and execute permission checks.

An exhaustive list can be found at http://kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html.

Scenario

Let's say you are running Ubuntu 10.04 and you have a user named andrew that needs to be able to run ifconfig commands in order to bring interfaces up and down. Historically the normal way to do this is somehow end up allowing andrew to run ifconfig as root, either with sudo or just setting the ifconfig executable setuid root. A much safer way to do this is to grant andrew the CAP_NET_ADMIN capability and set up the system to honor it. This way andrew never runs anything as root but he still gets to run his interface configuration commands.

The reason this is safer is because if there is ever an arbitrary code execution vulnerability discovered in the ifconfig program, the only thing andrew will be able to do is configure arbitrary network interfaces as he pleases. If he were running ifconfig via sudo or setuid root, he would instead be given root access and could do anything he wanted on the system.

Here's how we do it:

Granting the user the capabilities

First we have to grant andrew the cap_net_admin capability by adding this line to /etc/security/capabilities.conf:

cap_net_admin andrew

Note that this cannot be added at the end of the file, it must appear before the "none *" line or this won't work.

Configuring the system to grant capabilities on authentication

Now that we've given andrew the cap_net_admin capabilities we should make sure our system is set up to grant those abilities when andrew gets authenticated, so we edit /etc/pam.d/common-auth and make sure the line

auth required pam_cap.so

is in there somewhere. On a default ubuntu install this will say optional instead of required, find that line and change it to required.

Adding the capability flag to the executable

Finally we have to add the cap_net_admin capability flag to the ifconfig executable, like so:

setcap cap_net_admin=ei /sbin/ifconfig

This adds the cap_net_admin capability to the effective and inheritable sets of the ifconfig executable. Effective means it is enabled and inheritable means any program ifconfig calls will also have this capability.

Once all that is done and we re-log in as andrew, this user can now run the ifconfig command and change network configuration without having to sudo to root.

TL;DR

  • Add "cap_net_admin andrew" to /etc/security/capabilites.conf before the "none *" line.
  • Change "auth optional pam_cap.so" in /etc/pam.d/common-auth to "auth required pam_cap.so".
  • Run "setcap cap_net_admin=ei /sbin/ifconfig".

References

http://www.linuxjournal.com/magazine/making-root-unprivileged?page=0,1