What Is SELinux?Security Enhanced Linux (SELinux) is a set of modifications to the Linux kernel that implement mandatory access control (MAC) and role based access control (RBAC). SELinux utilizes policies to know the rules it needs to enforce. Like other mandatory access control mechanisms, SELinux policies are defined by the system administrator.
SELinux operates on a least privilege principle. The least privilege principle says that an entity should have enough to do their job, nothing more, nothing less. SELinux allows administrators to have granular control over resources on the system to enforce rules based on this principle. For example, standard Linux access controls allow a user to read, write, or execute a file and control these permissions if they own the file. Those same permissions apply to the applications that the user runs. All of these permissions apply even if they are not really necessary. For instance, with SELinux, an administrator can determine what a user is allowed to do on a given resource versus what an application that runs as that user is allowed to do. Let's say you do not want your browser to access files in your home directory. You can do that with SELinux.
Where Can I Get SELinux?SELinux is installed and enabled by default on all Red Hat Linux based Linux distributions like CentOS, Fedora, and Red Hat Enterprise Linux. You can also install it on Ubuntu, Debian, and Gentoo.
SELinux ComponentsSELinux has several components that work together to enforce the security policy of the system. The first is you (or any user of resources on the system). A user of resources on the system is called the subject. The subject requests to perform some action (like reading a file) on an object. An object is a resource on the system like a file or network port. When a subject wants to perform an action on an object, it asks the object manager for permission. The object manager knows about the objects it manages, and enforces the policy on behalf of the security server. The security server is the one that actually makes the decisions based on the security policy. In order to not overwhelm the security server, the Access Vector Cache (or AVC) caches decisions made by the security server. That way, if a bunch of users want to do the same thing, they do not have to each ask the security server for permission. The AVC can grant or deny access on behalf of the security server.
Think of it this way. Let's say you (the subject) are in the office. You have an accounting officer (object manager for money) that you need to go through to acquire new equipment. All purchases have to be approved by the Program Director (security server) (or his deputy (AVC) if he is busy). Let's say you need to buy a new server to deploy your awesome new program. You are the subject and you want to take an action on the budget (use money) to buy the server. Since the accounting officer manages the money, you ask him. He says he needs to ask the boss. He asks the boss because the boss' deputy does not know if the boss would be okay with the purchase. The boss looks at his guidelines for taking actions on money (like purchasing - this is the security policy). There is enough money in the budget, so he says okay. You are getting a new server!
Let's say a number of similar purchases have been made. The deputy knows this, and so he approves your request without going to the boss. This is like AVC.
Now that we have an understanding of how the components of the system interact in an SELinux system, let's go into a bit more detail.
Users, Roles, Types, and Security ContextsWe have a few more definitions to get through before we get hands on with SELinux. Most of the time, your Linux user will be the same as your SELinux user, but not always. If you change users with su (or sudo), your SELinux user will not change (it stays the same for the entire session). Users in the context of SELinux have '_u' on the end (such as 'bob_u').
RolesA role in SELinux is a formal construct for a user's role on the system. Users and processes may take on multiple roles (like in real life). Roles are denoted with a '_r' on the end and do not apply to files. A common example is unprivileged user: unprivileged_r. I mentioned that SELinux implements Role Based Access Control, and SELinux roles are a mechanism that contribute to RBAC in SELinux.
Types and DomainsTypes (also called domains when applied to processes) in SELinux group items together into ways they can be accessed. Types are denoted with a '_t' on the end. This is probably easiest to describe with an example. All of the items in a user's home directory may be labeled with the type 'user_home_t.' You could define a policy that does not allow certain processes to access the files in a user's home directory (those files marked with type user_home_t).
Security ContextsA security context is a label consisting of the user, role, and type. These security contexts apply to objects on the system and help the security server determine who can get access (and how). A security context looks like user:role:type:range. We have not talked about range yet. Range is an optional field that only applies when using Multi-Level Security (MLS). MLS usually describes varying levels of sensitivity. An example would be classification levels of information such as public, confidential, and secret. We will not do too much with ranges and MLS. Instead, we will focus on users, roles, and types.
You can use the -Z switch on many utilities such as ls, ps, and ss to get information on the security contexts that apply to files (ls), processes (ps), and network sockets (ss).
You can see if SELinux is enforcing (actively enforcing the rules defined in the policy) with the sestatus command:
We can see here that SELinux is enabled and enforcing (current mode). There are three modes for SELinux:
- Enforcing: Rules defined in the policy (called targeted in this case) are being enforced and logged.
- Permissive: If an application tries to do something it should not do as defined by the policy, SELinux will not stop it, but it will log it. This is similar to the Audit mode we talked about with AppLocker and EMET. This mode is useful when you are testing rules to make sure they do not break your system.
- Disabled: SELinux is not logging or enforcing any rules.
You can change these temporarily (until the next reboot) using setenforce command. setenforce 1 (or setenforce Enforcing) will set SELinux into Enforcing mode, and setenforce 0 (or setenforce Permissive) will set SELinux into Permissive mode. If you want to make this change permanent or disable it completely, you will need to edit /etc/selinux/config and change the line that says SELINUX= to the mode you want to use then reboot.
A Practical ExampleThe reason people usually disable SELinux is because it appears to get in the way of whatever it is that they are trying to do. Let's say you want to set up a Samba server on your CentOS 7 (which, like older versions of CentOS, has SELinux enforcing by default). The first thing you will probably do is edit /etc/samba/smb.conf to set up your shares. For this example, I am going to use a share that is open to everyone. You would not do this in real life, but it works well to demonstrate this example:
[SharedFiles] path = /shared browsable = yes writable = yes guest ok = yes read only = no
I created the /shared directory, and assigned it with permissions so that it could be written to by anyone. That should work right? I can see the folder:
Let's try to open it up:
But I thought I enabled access for everyone. So what happened? At this point, you would probably go to Google and try to figure out the problem. After a few minutes, you would probably find out that this is SELinux at work. Samba is one of the services that the default SELinux policy protects on CentOS (and other RedHat Linux based distributions like Fedora). Remember that processes on an SELinux enabled system can be confined to certain domains (or resources marked with particular types). The default policy on CentOS confines Samba to only share out folders and files marked with the samba_share_t type. In other words, the Samba daemon is confined to files in the samba_share_t domain (at least for sharing). So in order to share our files out, we need to change the contexts for the directory we shared. We do that with two commands (as root):
sudo chcon -Rt samba_share_t /shared sudo semanage fcontext -a -t samba_share_t '/shared(/.*)?'
These might look confusing, and I do not want to give you commands to run without explaining them first, so we will take them one by one.
chcon changes the file contexts on a file or directory. The first command tells chcon to change the type (-t) recursively (-R) on the /shared directory to samba_share_t. This will change the context on any file or folder in /shared and /shared itself. However, this is only temporary. It does not change the default context for the directory. To do that, we need the second command.
semanage (part of the policycoreutils-python on CentOS / Fedora) allows you to set the file contexts permanently. The -a switch tells semanage to add the type (-t) samba_share_t to anything under the /shared directory. You can specify exactly what you want to apply the context to with Regular Expressions. The regular expression I used says match a slash then any number (*) of any character (.). That is enclosed in parentheses make a group. The ? says match that group one or more times. That group should cover anything in the root of the /shared directory and any sub-directories since sub-directories will look like this: /shared/dir1/dir2/file.ext . The first group would be /dir1, the second would be /dir2, and the last group would match on /file.ext . If you want to learn more about Regular Expressions, I have included a few links at bottom of the post.
After we run those commands, let's see what happens.
I can see the folder now, and I can even access files as I expected:
If you want to get deeper into configuring Samba on an SELinux system, I have put a link at the bottom of the post.
Now that we understand a bit about SELinux and policies, I want to talk a little about our little example from a security perspective.
What SELinux Is and Is NotLike EMET and AppLocker, SELinux is not a silver bullet. SELinux will not stop actions that are allowed in policy but might be malicious. For example, if the Samba service were compromised on a box that has the default Samba SELinux policy, it would be able to destroy or alter any files that were shared by the server. That is the same as if SELinux were not there. The difference is that if the Samba service were compromised on an SELinux system and the attacker were confined to the actions that are defined in the Samba policy by default, the attacker would not be allowed to do some things they might be otherwise.
For example, they would not be allowed to access any files marked with types not specifically allowed by the policy. SELinux operates on the principle of least privilege that we talked about before. That means that by default, actions are denied until you allow them. So that means that Samba cannot access files marked with user_home_t (a file in a user's home directory) even if they are world readable unless you allow that.
Another good example is let's say you are running a process as your user (like a browser) that is denied to access files in user home directories. If the browser is compromised, the attacker will not be able to access the files in your home directory either. This is because the browser is confined by policy to not be allowed to access files in your home directory even if the process is running as your user. On a system without SELinux, the compromised browser could read your home directory.
So there certainly is value in SELinux, but it is only as good as the policies that it is enforcing. There have been bypasses in the past for SELinux (just like there have been for EMET and AppLocker). Attackers are also going to build attacks for the default policies because most people do not take the time to customize or alter these policies. This is true with AppLocker as we saw last week.
So Why Should I Keep SELinux Enabled?This does not mean that SELinux should always be disabled. It is another layer in your layered defense strategy. It should stop the easy things, and make it a bit harder for someone to operate without throwing up flags.
I think that if you genuinely care about the security of the boxes that run SELinux, you will take time to try to make SELinux work for you. While it is not the most intuitive security measure to manage and deploy, it has benefits that will help in the event of a compromise. With that being said, I think that SELinux's biggest challenge for adoption is the relative difficulty of administration and deployment.
I am not saying it needs to be dumbed down, but it needs to be more accessible. I do not think most people mind reading more about a defense measure to learn how to use it properly if they believe it does something valuable for them. However, there are practical constraints. Most people cannot spend weeks or months trying to get something working when there is real work to be done, and that is the trade off between usability and security. SELinux has made strides to make it easier. For example, when you try to do something, and it is denied, the audit log (/var/log/audit/audit.log, look for log events with the AVC type) often has clues as to why the action was denied. The tool sealert (in the setroubleshoot or setroubleshoot-server packages) can help you diagnose issues and will even give you commands to run to fix issues.
Perhaps the issue is one of perception. Windows boxes are often targeted, so people feel a more compelling need to seek out security measures to protect Windows boxes than Linux boxes. There seems to be this idea that if you are not running Windows you are safe because attackers seem to go after Windows boxes more often. There are more exploits for and attacks against Windows because Windows has a higher market share on the desktop than its competitors, but this is not true in the server, mobile, or embedded spaces. Also, just because you do not see an attack happening does not mean it is not happening. Better hackers are aware of various defense mechanisms and have worked on ways around them to elude detection.
Final Thoughts and ConclusionsThe point of this post was to help you demystify SELinux even if just a little bit. I would be curious to hear your thoughts about SELinux. Do you disable it immediately? Please let me know. Thanks for reading!
References and Further Reading
SELinux Users and Administrators Guide
SELinux Project Documentation
SELinux Samba Documentation
Writing SELinux Policies
SELinux For Mere Mortals (Video Presentation)
Regular Expressions Tutorial
Regular Expressions Tester