Joshua Brindle

How to Win At Security

The Future of SELinux (or how we are going to take over the world)

I've been talking to a few people about what SELinux might look like in a few years and the conversations have been fairly stimulating so I'm going to share some of the ideas here.

As you (hopefully) know in my day job I work on the SELinux policy server, which as far as I know, is the most forward looking SELinux project around. Granted all those forward looking goals aren't published on the site, hopefully we can remedy that at some point.. So alot of this is going to be centered around the policy server, other parts are just on my wishlist.. without further ado lets get started...

I think the absolute most important thing that needs to happen is that SELinux needs to become part of the system, not a strap on, not a value add, not an extra burden, it must be part of the system. There are a ton of things that need to happen for that to happen, most of the desires below will, in some way, reflect on this main goal.

First and foremost we need complete protection. Its been said many times in the past and its still true. If SELinux desktop deployments are ever going to be entirely secure a security enhanced X server is necessary. Without it even a confined mail client or web browser can use the X protocol to manipulate or otherwise hijack other applications running in X. This isn't something that can be solved any way except by making X an object manager. This work has been done, I personally have run a security enhanced X server for extended periods of time but without a proper integration into upstream and proper deployment by distributions it won't help. In addition to the enhanced X server the window manager must be SELinux aware. This means that the window manager is capable of launching applications in different domains, managing clipboard data and ensuring it doesn't allow information to be leaked from one domain to another without permission and many other things. Once these two things are in place we are well on our way toward SELinux utopia.

One of my biggest desires is to use SELinux to its potential and make the root user powerless by default. Ubuntu has started on this path already, making the root user not able to login and forcing users to use sudo to do administrative tasks. This is a disruptive concept that many many people won't like but it must happen. Once the root user is powerless by default SELinux roles are used to manage administrative tasks and grant only what is necessary to each user, which brings me to my next point.

Fine grained role management is an absolute must. The SELinux reference policy already has concepts that will allow this to be implemented in the (hopefully) near future. Each policy module should export some sort of role capabilities (not to be confused with Linux or POSIX capabilities) that can be granted by the system administrator. For example, the Apache module should have an interface that, when invoked, gives a role authorization to administer Apache, whatever that means. Once the policy is running on the system the administrator should be able to specify the precise capabilities that any role is able to use. This brings me to my next point.

The user management and selinux role and user management must be unified. An administrator should absolutely not need to go to a different application or dialog box to give a user that he just created extra SELinux privileges. SELinux must be a first class citizen of the system. In the user management interface the SELinux options must be present and easily usable. For example, my small company just hired a new junior admin. I want this admin to administer a handful of daemons, including apache. The interface where I create him as a user should have a very obvious way of customizing his roles capabilities (this depends on the fine grained role management). Everything about the system must be unified, which, again, is my main point, SELinux must be part of the system, not an addon.

When I want to adjust my firewall settings SELinux settings should be present. We already know that SELinux is capable of much more fine grained network controls, specifically that you can specify specific domains that can access the network in specific ways. The example I want to use here is Firefox. I want my enterprise to enforce that each workstation must have two web browsers, one that is intranet only and one that is internet. This will allow me to prevent any kind of Firefox exploit from touching my internal network. The network management should be able to let me specify that I want two Firefox domains with different network access controls. We'll put two firefox icons on the desktops and SELinux will take care of the rest.

We shouldn't just have fine grained access of client sessions though. One of the biggest problems plaguing the Internet is that web servers are notoriously insecure. When a random untrusted user's PHP scripts are allowed to run in the same domain as trusted system scripts there is clearly a problem. Apache should be able to bracket privileges of user and system scripts, or even fine grained bracketing between different classes of users. The most secure and effective way to do this is to execute interpreters per target domain. FastCGI basically does this for DAC already. When a user's script is accessed FastCGI determines if there is already an interpreter running as that UID that can handle the request, if not it will spawn one. We need to take this one step further and make a system like FastCGI spawn interpreters per UID per domain. This would make an enormous difference in the security of webservers and should be the default configuration. Alternatively for people who truly have performance requirements Apache chould use dynamic transitions to bracket privileges, though I don't suggest this as a permanent mode of operation.

Speaking of privilege bracketing, it would be very nice for other applications to do this as well. The systems package manager (we'll assume RPM for now) should be able to do a few things. The proper RPM process will have access to do pretty much anything, thats a given. That doesn't mean, for example, that arbitrary scripts that execute as part of the install process should have unlimited access to the system. RPM is already able to execute scriptlets in a different domain so we are partially there. One interesting thing I'd like to see is RPM being able to treat 'trusted' and 'untrusted' packages differently. We'll assume packages coming from the distro are trusted and third party ones are untrusted. An untrusted RPM should be much more restricted on the system, both the scriptlets and the RPM process itself. An untrusted application shouldn't be able to overwrite high integrity binaries or configuration files (think /usr/bin/passwd and /etc/shadow) or label files with high integrity labels (like passwd_exec_t). Firther the scriptlets should not be able to overwrite files on the filesystem or any of the other nasty things scriptlets like to do. This is disruptive as well since there are probably about a million RPM packages around that do seriously questionable things.

Since RPM also installs SELinux policy the same bracketing should apply there. Using the policy server one should be able to restrict the kind of policy an untrusted RPM can insert (while still allowing them to insert policy for the application being installed). For example a third party RPM like Opera (hypothetically ofcourse) should be able to install the browser policy but should not be able to add rules that let it (or anything else for that matter) access /etc/shadow. Nor should be allowed to overwrite any system binaries or libraries. A production ready policy server (we are working on this, I promise :) ) and an effective metapolicy would be necessary for this requirement.

Since one of the most critisized aspects of SELinux is its inability to apply fine grained controls to network filesystem this should also be added. This is alot more complicated than it seems at first, the network protocol should be sufficiently protected enough that the file labels sent across can be trusted. The client and server must also agree on an access control policy otherwise unexpected things can result. The client won't be able to subvert the policy on the server side but since many network filesystems are caching the user might not understand why a write succeeds but is reverted when the client flushes its cache to the server. Network security servers like Samba should be able to take advantage of SELinux by applying access controls to the incoming clients.

SELinux management, up until now, has been very focused on the policy itself. This isn't how administrators or users think, however. If someone wants to give user bill write access to a file in /usr/local/bin/bills-script he won't think to go to a policy, he'll instinctualy go to either the object itself (/usr/local/bin/bills-script) or to bill in the user manager. Either interface should be able to manage SELinux permissions. Chances are most people aren't going to learn how to write SELinux policy (most people didn't learn how to write files and look what happened there!). Simple permission assignments like this should be taken care of by the SELinux management tools, and should be transparent (why do they care what needs to be done to give access, they just need it).

This solves some problems but most applications written are applications run within an organization which means there are going to be alot of applications running on SELinux systems that no policy developer has ever seen, or ever will. The process of writing a policy for these applications must be made significantly easier. I've posted about how bad status quo encapsulation is in the past but at this juncture an application running a status quo style policy is better than it running without one at all. The system should be able to write a policy for the application with very little interaction from the administrator. This will always leave the ability for more savy admins and users to write well thought out policies for their applications but we need an 80% way to write policies that will help the vast majority of people.

SETroubleshoot is a very good first step toward a widely usable SELinux but it needs to go even further. More targets need to be written for it so that it understands most denials. If most expected denials can be caught and dealt with the remaining denials may be indicative of an actual problem on the system, like an attack, something that an administrator should be notified of. By eliminating as many false positive denials as possible SELinux auditing could become useful as an early warning system for attempted intrusions and other bad things.

One of the most important things that SELinux can do is educate software developers and companies that their software is broken and how they can fix it. I allude to this in another blog article but this will be the most help to the most people. If most systems are running SELinux and users tell vendors that disabling it isn't an option that will force them to fix their software for the betterment of all of their users. I hope that this will be one of the most significant impacts SELinux can make on the entire industry for opensource applications, commercial applications and even internal applications.

Oh, one more thing, we need a really cool and secure looking framebuffer graphic that is shown during bootup, that way people know we are really secure :)