SELinux - very handy

· by Steve · Read in about 5 min · (930 Words)

Those NSA techs know a thing or two about security - you’d kind of hope that was the case I suppose, especially if you’re part of the world’s current dominant superpower (at least for now ;)). They came up with SELinux in response to a need for kernel-level mandatory access controls which were very configurable to many levels of security clearance, and indeed in its entirety it’s a pretty complex policy-driven security system which greatly enhances both the granularity and strength of security policies over and above the typical Directory Access Control (DAC) approach you get with regular Linux filesystems. Basically on the user/process end you get domains and roles, and on resources (files, ports, other accessed ‘things’) you set up types - all these are very extensible. Then you set up policies which link those together in different contexts.

Most of what it can do is seriously overkill for most of us who don’t deal with classified resources. However, it has a significant advantage - it makes a fantastic safety net for isolating hacked services.

We’re all careful about security - we try to stay up to date with the latest security fixes, we take heed of the various configuration recommendations, and try our damndest not to get hacked. But, sooner or later you’re probably going to have to deal with some level of intrusion, via a zero-day flaw or just an oversight. It happens, much as we might hate it. So, assuming that eventually something is going to get compromised, the next question is how you isolate the damage. When someone does get in through a public service, let’s make sure the havok they can wreak is limited to certain areas.

In the past, we’ve addressed that on to some degree through chroot jails. This is where a service is started up in such a way that it’s root directory is not the real root directory, but an isolated subsection of the filesystem. The idea being that even if the service is compromised, the errant process is only able to ‘see’ that area of the filesystem and not the whole machine. The downside is that you have to copy all the software the service needs into that new subsection of the filesystem, which can lead to a lot of chasing dependencies using ‘ldd’ and manually copying libraries during setup. The other issue is that chroots aren’t completely foolproof - it is possible to break out of a chroot jail if you’re a user with root privileges - and whilst no well-configured webserver runs as root, a series of mistakes could lead to a file with the setuid bit enabled allowing privilege escalation. To exploit this requires a combination of compromised things on the server, which makes it unlikely but not impossible. Still, chroot is certainly better than nothing - without it, a compromised webserver combined with some lax directory permissions can mean locating all the effects of a breach can be difficult.

So, what does SELinux do to help? Well, it basically intercepts all requests at a kernel level and applies the configured policies, meaning that if that policy says a process in a certain domain can’t do something, it can’t. Period. Even if it somehow manages to execute a setuid file or something like that, SELinux would still block it. That’s because what matters is the original process domain, and not what the process has managed to change to via a privilege escalation. Also, after getting past directory permissions, there’s an extra check - so if you accidentally changed some permissions somewhere so that all users could write them (oops), without SELinux apache could go nuts in that area - but with SELinux, it’s prevented because the policy says Apache is only allowed to write in areas which are explicitly marked as a specific httpd writable type. It’s like having a second level of very conservative defense.

Since SELinux is implemented at the kernel level, it’s not something you can bypass via installing local binaries through a hack either. And whilst configuring all these policies is very daunting, luckily you don’t have to do it yourself, because there are prewritten policies for all the most popular services. Whilst the NSA undoubtedly runs in ‘strict’ mode, which means absolutely everything is checked via SELinux, most people will run SELinux in ‘targetted’ mode, which means it only monitors specific daemons - most obviously httpd, named, mysqld etc. After enabling it, you’ll find that your webserver is running in its own domain (called httpd_t) which is subject to a number of very sensible policies, like only being able to read and execute scripts from certain locations, and not being able to write anything. You can explicitly allow access to other areas by changing extended file flags - an explicit opt-in process that is far less likely to be accidentally used or leaked like chmod.

I’ve enabled SELinux on our new server (it’s bundled in RHEL, and Fedora too) and am starting to explore it. We do have a few scripts which need to write data to the filesystem (like avatar uploads) so there will need to be a folder or two tagged that way, but it’s really nice to know that no matter what happens, something compromised in the web server can’t ever write anywhere else. This is even better than a chroot jail and I’m very glad I discovered it. Whilst we all hope that a compromise never occurs, knowing precisely how far it can possibly go is a great comfort for if, heaven forbid, the unthinkable should happen.