This post appeared originally in our sysadvent series and has been moved here following the discontinuation of the sysadvent microsite
I’ve always had a bad conscience about the audit trail on the servers I manage. Sure, we use personal accounts and sudo, so we know who ran every command. Unfortunately, the command in the sudo log is often just “bash”.
The reason for this is simple: It is quite awkward to work in the shell when TAB completion doesn’t work. You want to read the error log in /var/log/httpd? Too bad, the directory is off limits for normal users. So what is the filename? Well, first run “sudo ls” on it, then cut and paste the filename after “sudo less”. No, that will make me go mad. “sudo -i” it is.
After lamenting about this recently I had a lightning bulb moment: Isn’t this the sort of thing Linux capabilities(7) set out to handle? And lo and behold:
CAP_DAC_OVERRIDE
Bypass file read, write, and execute permission checks. (DAC is
an abbreviation of "discretionary access control".)
CAP_DAC_READ_SEARCH
* Bypass file read permission checks and directory read and exe‐
cute permission checks;
The first one is really powerful - it allows all read and write access to files, as if you were root.
The other one is exactly what we need. It allows all getdents(2) and stat(2) calls as if you were root.
How do capabilities work?
Capabilities are a set of permissions which are granted to an executable. Not a process, not a user, not a session. The original use case for capabilities was tcpdump, shortly followed by ping. Let’s have a look:
$ ls -l /bin/ping
-rwxr-xr-x. 1 root root 44752 Nov 19 2015 /bin/ping*
The period after r-x indicates the file has extended attributes, and capabilities are among them. Other than that there are no other special features.
$ getcap /bin/ping
/bin/ping = cap_net_admin,cap_net_raw+ep
This is what grants ping the ability to send raw ICMP packets on the network, even if the user isn’t root. Before capabilities came along, ping was typically setuid root. In ping’s case, we don’t mind that every user gets access to this ability, but for a shell it would raise privacy issues.
Applying capabilities to bash
Let’s try it out:
cp /bin/bash /tmp/testsh
chmod 700 /tmp/testsh
sudo setcap CAP_DAC_READ_SEARCH=ep /tmp/testsh
=ep
means effective and permissive. Don’t blame me for obtuse
syntax :-).
If you run /tmp/testsh now, you will be able to use TAB-completion within /var/log/httpd/ or wherever else you like. Try it out! Go wild! You will still need sudo to do destructive operations. You can check the capabilities of a process like this:
$ grep CapPrm /proc/$$/status
CapPrm: 0000000000000004
Notice that bit 4 is set. Compare with:
$ grep CapPrm /proc/self/status
CapPrm: 0000000000000000
Here /proc/self
is the grep
process spawned by the shell, so this
demonstrates that the capability is not inherited by child
processes.
Adding tabashco!
Having your own personal /tmp/testsh
is fine, but it would be better
to share it with your sysadmin colleagues.
As mentioned earlier, the capability is granted to the program, so we need to use Unix permissions to restrict access to these super powers. A common denominator for access could be membership in the group “wheel”.
Basically, we create a copy of /bin/bash
, chmod it to 550 and change
its group. After a brief brainstorming (“adminbash”, “tab-bash”,
etc.), I ended up with “tabashco” (not a trademark - yet).
The Puppet code to make this copy looks like this:
class baseconfig::tabashco(
$path = '/usr/local/bin',
$group = 'wheel',
)
{
file { "${path}/tabashco":
source => '/bin/bash',
owner => 'root',
group => $group,
mode => '0550',
}
exec { "setcap cap_dac_read_search=ep ${path}/tabashco":
path => '/usr/sbin:/sbin',
refreshonly => true,
subscribe => File["${path}/tabashco"]
}
}
Puppet will make sure that tabascho
is updated whenever /bin/bash
changes.
Finally, you need to put code like this in your ~/.bash_profile
(or
in a file in /etc/profile.d
)
if [ -x /usr/local/bin/tabashco ]; then
case $0 in
*tabashco) : ;;
*) echo "Spicing up your shell!"
exec tabashco "$@" ;;
esac
fi
PS: Don’t let the PHP users know that they can do setcap
CAP_DAC_OVERRIDE=ep /usr/sbin/httpd
On the other hand, perhaps you
should - after all it is better than chmod -R a+rwx /
)
Thoughts on the CrowdStrike Outage
Unless you’ve been living under a rock, you probably know that last Friday a global crash of computer systems caused by ‘CrowdStrike’ led to widespread chaos and mayhem: flights were cancelled, shops closed their doors, even some hospitals and pharmacies were affected. When things like this happen, I first have a smug feeling “this would never happen at our place”, then I start thinking. Could it?
Broken Software Updates
Our department do take responsibility for keeping quite a lot ... [continue reading]