🌐 🇵🇱 Polski · 🇬🇧 EN
SELinux (Security Enhanced Linux) is a set of Linux kernel modifications and methods for resource allocation for applications. Every process and file in the system has a specific type. Different processes are designed to perform different tasks and interact with different types of files. SELinux establishes rules that define how specific processes gain access to files. Access to specific files is possible only if the appropriate SELinux rule permits it. This is an additional security tool that goes beyond the capabilities offered by standard tools such as groups, users, and ACLs that define file access permissions.
SELinux implements many different security policies such as:
SELinux implements many different security policies such as:
- Mandatory Access Control (MAC)
- Flux Advanced Security Kernel (FLASK)
- Role-based access control (RBAC)
- Type Enforcement (TE)
File access rules for specific processes are defined by the contexts set on those files. To check what context a given object has (this can be a file or a directory), we use commands that list files with the appropriate switches:
# ls -Z
# ps -Z
# ps -Z
In UNIX systems, there is a saying that "everything is a file". Traditionally, file access is controlled using user accounts, groups, and permission level configurations. In the case of SELinux, we can slightly modify the main saying to "everything is an object", and access control relies on security elements placed in extended attribute fields. Generally speaking, these are fields called security contexts. This set consists of (though not in every system) 5 elements.
To see what context is set on a given file, we use the file listing command "ls" with the "-Z" switch.
Generally speaking, files inherit contexts from directories:
# ls -Zd /etc/ /etc/bashrc
drwxr-xr-x root root system_u:object_r:etc_t:s0 /etc/
-rw-r--r-- root root system_u:object_r:etc_t:s0 /etc/bashrc
Whether SELinux will be enabled or disabled after a system restart is determined by the configuration file:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
- user - Indicates the type of user logged into the system. If the logged-in user is "root", the value of this element will be "root". The value for other users will be "user_u". If we escalate our privileges using "su", this value will remain unchanged as "user_u". For processes, this value is defined as "system_u".
- role - Using the role parameter, the purpose of a specific file, process, or user is defined. Files have the "object_r" parameter as their role. For processes, the role "system_r" is set. Users also have the "system_r" parameter as their role, because in Linux, processes can be considered objects similar to users.
- type - The application of the type parameter is intended to represent the nature of the data present in a given file or process. The rules contained here define which type of process can have access to a given type of data.
- sensitivity - Security classifications sometimes used by government agencies.
- category - Similar in operation to system groups, but has the ability to block access to data even from the "root" user.
To see what context is set on a given file, we use the file listing command "ls" with the "-Z" switch.
# ls -Z /root/anaconda-ks.cfg /var/log/messages
-rw-------. root root system_u:object_r:admin_home_t:s0 /root/anaconda-ks.cfg
-rw-------. root root system_u:object_r:var_log_t:s0 /var/log/messages
# ls -Zd /etc/ /etc/bashrc
drwxr-xr-x root root system_u:object_r:etc_t:s0 /etc/
-rw-r--r-- root root system_u:object_r:etc_t:s0 /etc/bashrc
Some files have unique contexts for increased security.
# ls -Z /etc/shadow /etc/aliases /etc/hosts
-rw-r--r-- root root system_u:object_r:etc_aliases_t:s0 /etc/aliases
-rw-r--r-- root root system_u:object_r:net_conf_t:s0 /etc/hosts
---------- root root system_u:object_r:shadow_t:s0 /etc/shadow
If the system is to ensure a sufficiently high level of security, it is recommended that everything be configured under SELinux security restrictions. In RedHat 4, SELinux protected 13 processes, but in RedHat 5, their number increased to 88.
As with files, contexts also apply to processes existing in the system. Checking which context a given process is protected by can be done using the "ps -Z" command.
# ps -ZC rpcbind,bash,crond
LABEL PID TTY TIME CMD
system_u:system_r:rpcbind_t:s0 1312 ? 00:00:00 rpcbind
system_u:system_r:crond_t:s0-s0:c0.c1023 1800 ? 00:00:01 crond
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2238 pts/0 00:00:00 bash
Every process whose type is defined as unconfined_t is not subject to SELinux restrictions. An example of a process not subject to SELinux is the "bash" shell visible above.
To display all processes along with their SELinux contexts, we use the commands:
ps -eZ
ps Zax
Enabling and disabling SELinux
Whether SELinux will be enabled or disabled after a system restart is determined by the configuration file:
/etc/selinux/config
In which we can set parameters such as:
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
Above is the content of the configuration file, which, thanks to the included comments, does not need explanation, but for those who do not know English, it can be said that SELinux can operate in three modes:
- enforcing - security policies enabled
- permissive - policies disabled but monitored, providing messages about their activity
- disabled - SELinux policies not running
TARGETED POLICY
In RedHat Enterprise Linux, the default SELinux security policies are those referred to as "targeted". If we use targeted SELinux policies, it means that processes are run within an existing domain. For example, by default, a logging-in user gets a context from the "unconfined_t" category, and running system processes have the default "initrc_t" context. Both the user and the processes have no restrictions.
Both restricted and unrestricted objects are subject to permission checks enabling writing and executing code in memory. By default, objects with unset and unrestricted contexts do not have write and execute permissions, which is a restriction protecting against memory buffer overflows. Memory control can be bypassed using appropriate boolean variables.
The setting for the type of policies used is found in the previously mentioned file:
# vim /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
SELINUX=enforcing
# SELINUXTYPE= type of policy in use. Possible values are:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
SELINUXTYPE=targeted
RESTRICTING PROCESSES
Almost every service such as sshd or httpd running and listening on the network has appropriate context settings intended to introduce restrictions and ensure proper security. Most processes run with "root" privileges also have restrictions; a good example here is the passwd command. Restricting a process with a given context means running it in its own separate space; for example, the web server service, httpd, has the httpd_t context. Assigning "its own space" - a context for a given process - is significant in case the service is attacked. The applied context limits the attacker's room for maneuver (even if they manage to attack the given process or service) to the space of that process only, preventing them from moving beyond its scope to other services in the system.
Example demonstrating how contexts work.
The example will show how SELinux security prevents the apache web server service (httpd) from reading files that have not been properly labeled, such as files intended for the SAMBA service. Please remember that this is only an example of operation and should not be used in production environments.
To perform this exercise, the httpd and wget services must be installed on the system. SELinux must be enabled in enforcing mode.
Step 1 - Checking SELinux operation
# sestatus
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 24
Policy from config file: targeted
The above result of the "sestatus" command indicates that SELinux is running in the correct mode.
Step 2 - While logged in as "root", we create a test file for the web server
# touch /var/www/html/pliktestowy
Step 3 - We check the SELinux context of the created file
# ls -Z /var/www/html/pliktestowy
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/pliktestowy
By default, RedHat Enterprise Linux system users operate in a mode unrestricted by contexts, which is why the created test file has a context labeled as "unconfined_u". In the case of files, the set role "object_r" has no significance. The next entry visible in the context, "httpd_sys_content_t", means that the httpd service has authorized access to this file.
Step 4 - With "root" privileges, we start the web server service
# service httpd start
Starting httpd: [ OK ]
Step 5 - We navigate to a directory where the currently logged-in user has read and write permissions and download the file using wget.
# wget http://localhost/pliktestowy
--2013-09-04 10:22:24-- http://localhost/pliktestowy
Resolving localhost... 127.0.0.1
Connecting to localhost|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13 [text/plain]
Saving to: “pliktestowy”
100%[======================================>] 13 --.-K/s in 0s
2013-09-04 10:22:25 (451 KB/s) - “pliktestowy” saved [13/13]
The file should be downloaded without any problems.
Step 6 - Using the chcon command as "root", we change the context of the created file.
# chcon -t samba_share_t /var/www/html/pliktestowy
We check if the changes have been applied
[root@margib-centos ~]# ls -Z /var/www/html/pliktestowy
-rw-r--r--. root root unconfined_u:object_r:samba_share_t:s0 /var/www/html/pliktestowy
Step 7 - After changing the context, let's try to download the created file again
# wget http://localhost/pliktestowy
--2013-09-04 10:30:28-- http://localhost/pliktestowy
Resolving localhost... 127.0.0.1
Connecting to localhost|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2013-09-04 10:30:28 ERROR 403: Forbidden.
The SELinux security mechanism worked and prevented the httpd service from accessing the file, so it is no longer available through this service.
Information about the denied access will also be recorded in the log:
# /var/log/audit/audit.log
type=AVC msg=audit(1378283428.681:25897): avc: denied { getattr } for pid=2207 comm="httpd" path="/var/www/html/pliktestowy" dev=dm-0 ino=664816 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:samba_share_t:s0 tclass=file
and in the log:
/var/log/httpd/error.log
[Wed Sep 04 10:30:28 2013] [error] [client 127.0.0.1] (13)Permission denied: access to /pliktestowy denied
After completing the exercise, you can remove the unnecessary files and stop the httpd service
# rm -rf /var/www/html/pliktestowy
# service httpd stop
CHANGING CONTEXTS - chcon COMMAND.
As you can see in the exercise above, the chcon command is used to change contexts. We perform the change in the following way:
# ls -Z post-install.log
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 post-install.log
# chcon -t etc_t post-install.log
# ls -Z post-install.log
-rw-r--r--. root root system_u:object_r:etc_t:s0 post-install.log
We can also change the context by referencing another file, so that the file whose context we are changing will have the same context as the one we are referencing.
# ls -Z anaconda-ks.cfg
-rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
# chcon --reference /etc/shadow anaconda-ks.cfg
# ls -Z anaconda-ks.cfg
-rw-------. root root system_u:object_r:shadow_t:s0 anaconda-ks.cfg
For security, it is possible to restore default system contexts for files; for this purpose, we use the restorecon command.
# restorecon /root/*
# ls -Z /root/
-rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 post-install
SELinux MANAGEMENT
SELinux can operate in the following modes:
- Enforcing
- Permissive
- Disabled
The command to check if the SELinux service is enabled is: getenforce.
# getenforce
Enforcing
Enabling or disabling the service can be done with the command: setenforce 1|0
# setenforce 0
# getenforce
Permissive
# setenforce 1
# getenforce
Enforcing
Setting SELinux boolean variables for individual services can be checked with the command: getsebool. For the httpd service, it looks as follows:
# getsebool -a | grep httpd
allow_httpd_anon_write --> off
allow_httpd_mod_auth_ntlm_winbind --> off
allow_httpd_mod_auth_pam --> off
allow_httpd_sys_script_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_network_connect --> off
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
httpd_can_network_memcache --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> on
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
httpd_execmem --> off
httpd_manage_ipa --> off
httpd_read_user_content --> off
httpd_run_stickshift --> off
httpd_setrlimit --> off
httpd_ssi_exec --> off
httpd_tmp_exec --> off
httpd_tty_comm --> on
httpd_unified --> on
httpd_use_cifs --> off
httpd_use_fusefs --> off
httpd_use_gpg --> off
httpd_use_nfs --> off
httpd_use_openstack --> off
httpd_verify_dns --> off
Changing boolean variables for SELinux for a given service is done with the command: setsebool on | off
# setsebool allow_httpd_anon_write on
# getsebool -a | grep httpd
allow_httpd_anon_write --> on
DISABLING SELinux
The only way to completely disable the SELinux service is to change the SELINUX value in the /etc/sysconfig/selinux file to "disabled" and restart the operating system. You can also set the selinux=0 option in GRUB as a system boot option. The SELINUXTYPE value remains unchanged.
GRAPHICAL TOOLS for SELinux
For managing and configuring SELinux, there is also a graphical tool system-config-selinux, which is part of the policycoreutils-gui package.
If an application attempts to gain access not authorized by SELinux rules, it is blocked, and information about this fact will appear in the /var/log/audit/audit.log log.

Comments