You are on page 1of 8

Linux and Open Source

Part 1. Introduction to SELinux: Don't let complexity scare you off


By Vincent Danen April 26, 2011, 6:00 AM PDT

Takeaway: Vincent Danen acknowledges that some of the complexity of SELinux is intimidating, but if you spend some time with it, the payoff is heightened security and better control of your system. Most people who know Linux have at least heard about SELinux. SELinux, or SecurityEnhanced Linux, was originally developed primarily by the NSA (U.S. National Security Agency), as an implementation of the Flask operating system security architecture. Flask implements MAC (Mandatory Access Control), a means of designating what processes have access to what resources (be they network ports, files, and so on). A lot of work has been done to make SELinux as easy to use as possible, although at first glance it does look hideously complex. Since 2003, SELinux has been integrated into the mainline Linux kernel, and is fully supported in distributions such as Red Hat Enterprise Linux, Fedora, CentOS, Debian (disabled by default), Ubuntu, openSUSE, Hardened Gentoo, and others. On Red Hat Enterprise Linux and Fedora, SELinux is enabled at installation. There is a lot of information out there on SELinux; a lot of it, if you look at it quickly, may scare you off of SELinux. Dont feel bad, it did the same to me as well. When I was developing Annvix, I opted to use AppArmor instead of SELinux because it seemed like the easier of the two and offered nearly the same end-result functionality. If I had to make that choice again, today, I would choose SELinux, however. From a security standpoint, distributions and Linux vendors today do a herculean job of keeping Linux operating systems safe. This is good news for anyone using Linux; however, the bad news is that a lot of this is reactive security. If there is a vulnerability in Apache, the vendor will typically backport a fix and release an update. However, there is a window of vulnerability between when the fix is released and when the problem is made public; there may be an even larger window of vulnerability if this is something that hasnt necessarily been made public, but is already being exploited (the so-called 0-day flaws). SELinux and tools like it are designed to protect you from these flaws by offering proactive security mechanisms. For instance, if there were a flaw in Apache that allowed an attacker to make it display arbitrary files, this could be used to display the contents of files like /etc/passwd. This in turn makes it easier for an attacker to brute force SSH accounts by knowing in advance the account names to target. Typically, Apache doesnt serve this content, so under normal circumstances (unless there is a flaw in a PHP application, etc.) this information would not be disclosed. If SELinux were installed and in enforcing mode, access to this file would be denied because the SELinux policy would prevent it (since these files are of the wrong type for Apache to access).

So while you may be running a vulnerable version of Apache, or a web application with a flaw in it, SELinux would prevent that disclosure because Apache has no rights to that file (of course, SELinux will happily allow Apache to display files that it does have the rights to access). In this instance, SELinux is a mitigation that would prevent a fairly serious confidentiality breach until such a time as a patched Apache could be installed. In a situation such as this, you really only have four choices: Turn Apache off to prevent the flaw from being exploited (generally, this would be considered bad for business) Continue to run Apache in a vulnerable state and pray for a quick update from the vendor Roll your own update to fix it Use something like SELinux, AppArmor, or some other MAC system for the proactive system hardening and security features it provides. Speaking of features, SELinux has a number of features that make it compelling: It allows applications to query the policy, so they arent fully hidden from view, unlike with some other MAC systems. It allows in-place policy changes; this means you can change the policy without having to reboot in order to activate the changes (I well remember having to do this with RSBAC). It has control over process initialization, inheritance, and program execution this gives you the ability to write very flexible policies to suit your needs. It has control over file systems, directories, files, open file descriptors, as well as sockets (such as TCP, UDP, etc.), messaging interfaces, and network interfaces. Using SELinux, you can fully tweak your system for any kind of operation, be it a web server, file server, print server, even a desktop system can be suitably secured with SELinux. Of course, all of this comes at a price, and this is what puts most people off. SELinux is complex, and it becomes even more so when you have to write your own policies. Fortunately, distributions such as Red Hat Enterprise Linux and Fedora come with very comprehensive policies to cover a variety of situations. The policies are quite cookie-cutter, but if you want to change them to accommodate your own system (such as a web directory that exists in a place other than /var/www/html), you can easily do so. Finally, SELinux offers three modes: enforcing, permissive, and disabled. Most distributions that support SELinux out-of-the-box will have it set to permissive mode first. This tells SELinux to log violations, so that you can use your system and use the reports to build a suitable policy. In permissive mode, a violation is logged, but the access is granted. In enforcing mode, a violation would be logged and the access denied. Disabled, of course, allows access but does not provide any information on what would have been denied. So before disabling SELinux, consider keeping it in permissive mode. You may get a number of alerts, particularly on a desktop system, but these can be used to tweak policy, reducing the number of alerts you will receive later. Next time, I will look at some basics of SELinux and tweaking the policies, as well as identifying some of the tools that are used to monitor violations and modify policy.

Part 2. Practical SELinux for the beginner: Contexts and labels


By Vincent Danen May 10, 2011, 6:00 AM PDT

Takeaway: Vincent Danen gets into some of the basics of working with SELinux. Learn how to work with contexts, which include ports, processes, files, and directories, and labels. Last time, I Part 1. Introduction to SELinux what it is, what it can do, and really why you need it (or a system like it). It is especially important with reported (and fixed) security vulnerabilities on the rise, and each year brings more reports, and more updates for end-users to install. This data tells us that we are in greater need of proactive security measures now than we ever were before. And this is where software like SELinux fits in. There is a lot to SELinux, and were only going to touch on SELinux contexts and labels. Suffice it to say, SELinux policies contain various rules that allow interaction between different contexts. Contexts are ports, processes, files, directories, and so on. Instead of getting overwhelmed with the technical concepts of SELinux, well instead look at the practical side of using SELinux so that it doesnt seem quite as daunting. The first thing to do is determine what mode SELinux is running in:
$ getenforce Enforcing

The getenforce command tells us what mode SELinux is in. The possible modes are Enforcing, Permissive, or Disabled. Enforcing means that SELinux will report access violations and deny the attempt, Permissive tells SELinux to report the violation but allow it, and Disabled completely turns SELinux off. Ideally, if you are unprepared to run SELinux in Enforcing mode, it should be in Permissive mode. This can be set at boot by editing (on Red Hat Enterprise Linux and Fedora) the /etc/sysconfig/selinux file and setting the SELINUX option:
SELINUX=enforcing

This will ensure it persists across reboot. SELinux can transition from Enforcing to Permissive easily using the setenforce command. Providing setenforce with a 0 argument will put the system in Permissive mode, a 1 will set it to Enforcing. To transition to or from Disabled mode, you need to reboot after making the appropriate changes to the sysconfig file. Using setenforce can be a great way of troubleshooting problems; if the problem goes away after setting the system to Permissive mode then you know it is SELinux. If not, then it is something else.
# setenforce 0 # getenforce Permissive

To view the contexts that a process is running with, add the Z option to ps:
# ps auxZ | grep httpd system_u:system_r:httpd_t:s0 apache 30544 ? S Mar30 0:00 /usr/sbin/httpd 0.0 0.0 305612 6688

This tells us that the httpd process is using the httpd_t type, the system_r role, and the system_u user. More often than not, it is the httpd_t type you would be interested in. The Z option is also used with other commands, such as ls, cp, id, and others. For instance, to view your security context:
# id -Z unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

Or to view the security context associated with a file:


# ls -lZ /var/www/html/index.html -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html

Again, probably the most useful bit of information here is the type, in this case it is httpd_sys_content_t. As an example of how to quickly change the policy, assume that you do not put your websites in /var/www/, but rather use /srv/www/foo.com/html/ for your sites document root. You can configure Apache to use these directories as the DocumentRoot for various websites, but if you were to visit them, Apache would return an error because SELinux would disallow access. SELinux knows nothing about allowing Apache to these directories as of yet. To determine what type a file needs to have in order for Apache to access it, the above ls command tells us that the type we want is probably httpd_sys_content_t; after all, Apache by default serves files from /var/www/html/. Another, probably better, way is to use the semanage tool. This tool is used to show, and change, defined SELinux policy. We could also do:
# semanage fcontext -l | grep '/var/www' /var/www(/.*)? system_u:object_r:httpd_sys_content_t:s0 all files

This command tells semanage to list all fcontext entries (file contexts), and we hand that output to grep to search for and display /var/www. For brevity, the whole output is not shown, but the above confirms that /var/www/* has the httpd_sys_content_t type. So what we need to do is tell SELinux to give this same type to /srv/www/foo.com/html/*, so that Apache can serve up those files. This can be done by using semanage to add a new context:
# semanage fcontext -a -t httpd_sys_content_t '/srv/www(/.*)?' # semanage fcontext -l | grep '/srv/www' /srv/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0 # restorecon -Rv /srv/www

The SELinux policies here use regular expressions, so the above tells semanage to add (-a) a new fcontext with the type (-t) httpd_sys_content_t, and targets /srv/www itself and any subdirectories and files. We use semanage to list the fcontexts and search for any /srv/www entries, to verify it is in place, and then use restorecon to re-label and set the appropriate security context on the /srv/www directory and any sub-directories and files. At this point, Apache will serve content from that directory if configured to do so, because Apache has the right to read httpd_sys_content_t files and /srv/www/ will now be labeled correctly. The restorecon tool is used to set default contexts on files and directories, according to policy. You will become very familiar with this tool because it is used very often. For instance, if you move a file from a home directory to this web root, it will not immediately gain the appropriate security context because the mv command retains the existing context (cp will make a new context because it is making a new file). For instance:
% echo "my file" >file.html % ls -Z file.html -rw-rw-r--. vdanen vdanen unconfined_u:object_r:user_home_t:s0 file.html % mv file.html /srv/www/foo.com/html/ % ls -Z /srv/www/foo.com/html/ -rw-rw-r--. vdanen vdanen unconfined_u:object_r:user_home_t:s0 file.html

Apache is not, by default, allowed to serve up user_home_t files, so any attempt to display this file via Apache will fail with denied access. restorecon is required to re-label the file so Apache can access it:
# restorecon -v /srv/www/foo.com/html/file.html restorecon reset /srv/www/foo.com/html/file.html context unconfined_u:object_r:user_home_t:s0>system_u:object_r:httpd_sys_content_t:s0

Now the security context of the file is correct. Similarly, when going from Disabled mode to Permissive or Enforcing mode, SELinux will have to re-label the entire filesystem (effectively running estorecon /) because contexts are not set at all when SELinux is disabled. Once you wrap your head around these basics of SELinux, all of a sudden it is no more difficult to use than manipulating iptables firewall rules. Just as you would adjust your firewall to allow access to a new service, you adjust SELinux file contexts to allow applications and services to access them. Yes, it does require a little more work to set up, initially, but the security benefits are really quite useful, especially considering that the bulk of this kind of manipulation will only happen when initially setting up a system or adding new services. And getting into the habit of running restorecon on new files and directories as they are created isnt any more difficult than using ls on them to double-check their permissions. The next and final tip on SELinux will introduce us to SELinux logging, to detect access violations, and to some other basic SELinux commands.

Part 3. Practical SELinux: Port contexts and handling access alerts


By Vincent Danen May 16, 2011, 12:30 PM PDT

Takeaway: After introducing and recommending SELinux a couple of weeks ago, I followed up with some of the basics - learning about setting file contexts with the semanage tool. This time, Ill show you how to set other contexts, and also look at how to handle reported access violations. Previously, we concentrated on file contexts; yet another [...] After introducing and recommending SELinux a couple of weeks ago, I followed up with some of the basics - learning about setting Practical SELinux for the beginner with the semanage tool. This time, Ill show you how to set other contexts, and also look at how to handle reported access violations. Previously, we concentrated on file contexts; yet another common and useful type of context to set is one related to ports. Using Apache as an example again, we know that Apache typically listens to ports 80 and 443. Default policy allows for this. If we wanted to have Apache listen on port 888 as well, however, this would not be permitted. For instance, if you have:
<VirtualHost secret.foo.com:888> ...

in your httpd.conf file and attempted to restart Apache, it would fail as follows:
# service httpd restart Stopping httpd: [ OK ] Starting httpd: (13)Permission denied: make_sock: could not bind to address [::]:888 (13)Permission denied: make_sock: could not bind to address 0.0.0.0:888 no listening sockets available, shutting down Unable to open logs [FAILED]

What happened? Looking in /var/log/messages is a great place to start:


Apr 2 15:34:03 cerberus setroubleshoot: SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 888. For complete SELinux messages. run sealert -l b9797116-ceaa-4dc8-acbcb2fdb1dd1cfd

This is fairly useful and gives the exact command to view the alert in detail. The information used to construct this is stored in /var/log/audit/audit.log, but using sealert to view it is much easier:
# sealert -l b9797116-ceaa-4dc8-acbc-b2fdb1dd1cfd SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 888. ***** Plugin bind_ports (92.2 confidence) suggests ************************* If you want to allow /usr/sbin/httpd to bind to network port 888

Then you need to modify the port type. Do # semanage port -a -t PORT_TYPE -p tcp 888 where PORT_TYPE is one of the following: ntop_port_t, http_cache_port_t, http_port_t. ***** Plugin catchall_boolean (7.83 confidence) suggests ******************* If you want to allow system to run with NIS Then you must tell SELinux about this by enabling the 'allow_ypbind' boolean. Do setsebool -P allow_ypbind 1 ***** Plugin catchall (1.41 confidence) suggests *************************** If you believe that httpd should be allowed name_bind access on the port 888 tcp_socket by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # grep httpd /var/log/audit/audit.log | audit2allow -M mypol # semodule -i mypol.pp

The sealert tool offers a lot of information here, including suggestions on how to resolve the issue. Out of the three suggestions it provides, the first is the one we want. We need Apache to listen to this port. The third suggestion would work as well, but the first is the easiest of the bunch (provided the correct context is chosen). In this case, it isnt to be used for caching, but serving up content, so the httpd_port_t type is the one to use:
# semanage port -a -t http_port_t -p tcp 888 # semanage port -l | grep http_port http_port_t tcp 888, 80, 443, 488, 8008, 8009, 8443 pegasus_http_port_t tcp 5988

Incidentally, semanage port -l works the same for ports as semanage fcontext -l works for file contexts. In the above, we can see that the http_port_t type is now applied to port 888, and Apache should start. When it does, you can verify it is listening to the port with netstat:
# netstat -lpn --tcp | grep 888 tcp 0 0 :::888 LISTEN 28463/httpd :::*

If you make a mistake, it is easy enough to delete the type. Also, if you wanted to prevent a service from binding on a particular port, the semanage delete (-d) argument is used (the rest of the arguments are identical to the add command):
# semanage port -d -t http_port_t -p tcp 888 # semanage port -l | grep http_port http_port_t tcp 80, 443, 488, 8008, 8009, 8443 pegasus_http_port_t tcp 5988

The final tools to get a quick introduction are the getsebool and setsebool tools. SELinux has a number of boolean macros that allow or deny certain types of functionality. For instance, Apache has a mechanism to allow users to have their own personal web sites using the ~/public_html/ directory (which shows up as http://foo.com/~user/). By default, SELinux does not permit this type of functionality, as seen by the value of the httpd_enable_homedirs boolean:
# getsebool httpd_enable_homedirs

httpd_enable_homedirs --> off

This in itself isnt very descriptive, so semanage can provide further information:
# semanage boolean -l | grep httpd ... httpd_enable_homedirs -> off ...

Allow httpd to read home directories

Incidentally, using semanage boolean -l is a great way to see what booleans can be set and what they are used for. To enable allowing httpd to read home directories, we would use setsebool:
# setsebool httpd_enable_homedirs 1 # getsebool httpd_enable_homedirs httpd_enable_homedirs --> on

This will persist only while the system is running. To save this boolean change to the SELinux policy files, you must use the persistent change (-P) option to setsebool:
# setsebool -P httpd_enable_homedirs 1

There is, obviously, so much more to SELinux, but these are the basics. Knowing how to change boolean settings, how to change the ability to access certain ports, files, and directories, as well as how to obtain information on SELinux violations, should provide you with the confidence to give SELinux a try. It isnt nearly as scary as I thought it was a few years ago, and using SELinux now, on supported and recent distributions, will provide you with tools that are better and easier to use than those provided a decade ago. If you have been running a system capable of using SELinux, but have had it running in Disabled mode, you owe it to yourself to give it a try in at least Permissive mode. For a little bit of time and effort, it could save you when the next 0day flaw that is applicable to you comes around (and, honestly, they seem to be coming around a lot more often than they used to).

You might also like