Wondering about SELinux users on CentOS 7? Let us discuss.
A Linux kernel security module, SELinux brings heightened security for Linux systems.
As part of our Server Management Services, we assist our customers with several Linux queries.
Today, let us discuss SELinux users and how to fine-tune their access.
In order to begin, our Support Techs recommend having an account with Sudo privileges.
SELinux Users
We don’t create an SELinux user with a special command, nor does it have its own login access to the server. Instead, they are in the policy that loads into memory at boot time.
Different SELinux users have different rights in the system and that is what makes them useful.
When we enforce SELinux, each regular Linux user account maps to an SELinux user account. This enables a regular account to inherit the permission of its SELinux counterpart.
To view this mapping, we run:
# semanage login -l
In CentOS 7, the result will be like this:
Login Name SELinux User MLS/MCS Range Service __default__ unconfined_u s0-s0:c0.c1023 * root unconfined_u s0-s0:c0.c1023 * system_u system_u s0-s0:c0.c1023 *
Any regular Linux user account is first mapped to the default login.
Then, we have the root user that does not map to the “default” login. Rather, it has its own entry.
system_u is a different class of user, meant for running processes or daemons.
To see available SELinux users in the system, we can run:
# semanage user -l
The output will be like this:
Labeling MLS/ MLS/ SELinux User Prefix MCS Level MCS Range SELinux Roles guest_u user s0 s0 guest_r root user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r staff_u user s0 s0-s0:c0.c1023 staff_r sysadm_r system_r unconfined_r sysadm_u user s0 s0-s0:c0.c1023 sysadm_r system_u user s0 s0-s0:c0.c1023 system_r unconfined_r unconfined_u user s0 s0-s0:c0.c1023 system_r unconfined_r user_u user s0 s0 user_r xguest_u user s0 s0 xguest_r
To verify our guest, we look at the fifth column, SELinux Roles. SELinux roles are like gateways between a user and a process. If a role has the authorization to access a process domain, the users associating that role will be able to enter that process domain.
From the above table, we can see the unconfined_u user maps to the system_r and unconfined_r roles. Similarly, user sysadm_u is authorized for the sysadmr role, but guestu maps to the guest_r role.
The default login maps to the unconfinedu user, just like the root user maps to the unconfined_u user. Since the **default_** login represents any regular Linux user account, those accounts will be authorized for system_r and unconfined_r roles as well.
Hence, any Linux user that maps to the unconfined_u user will have the privilege to run any app that runs within the unconfined_t domain.
To demonstrate this, we run:
# id -Z
This shows the SELinux security context for root:
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Here, the root account maps to the unconfined_u SELinux user, and unconfined_u authorize for the unconfined_r role, which in turn authorize to run processes in the unconfined_t domain.
Moving ahead, our Support Techs suggest starting four new sessions with the four users This will help us switch between different accounts when in need.
- regularuser
- switcheduser
- guestuser
- restricteduser
Next, we switch to the terminal session as the regularuser. We execute the id -Z command from there:
[regularuser@localhost ~]$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
In this case, regularuser account maps to the unconfined_u SELinux user account, and it can assume the unconfined_r role. The role can run processes in an unconfined domain.
SELinux users on CentOS 7
Furthermore, let us discuss the benefits of SELinux users on CentOS 7.
SELinux in Action 1: Restrict Switched User Access
To see how SELinux can enforce security for user accounts, let us think about the regularuser account. Specifically, we do not want the user to be able to switch to other accounts, including the root account.
Initially, let’s check the user’s ability to switch to another account.
For example, here, the regularuser switches to the switcheduser account.
We assume he knows the password:
[regularuser@localhost ~]$ su – switcheduser
Password:
[switcheduser@localhost ~]$
Then, we go back to the terminal window as the root user and change regularuser’s SELinux user mapping. We will map regularuser to user_u.
# semanage login -a -s user_u regularuser
We are adding (-a) the regularuser account to the SELinux (-s) user account user_u. The change will not take effect until regularuser logs out and logs back in.
Going back to regularuser’s terminal window, we first switch back from switcheduser:
[switcheduser@localhost ~]$ logout
Next, the regularuser also logs out:
[regularuser@localhost ~]$ logout
We then open a new terminal window to connect as regularuser. Next, we try to change to switcheduser again:
[regularuser@localhost ~]$ su – switcheduser
Password:
Eventually, we will see:
su: Authentication failure
Now if we run the id -Z command, we will see the output is quite different:
[regularuser@localhost ~]$ id -Z user_u:user_r:user_t:s0
We can stop the switch from happening by restricting their ability to switch accounts.
SELinux in Action 2: Restrict Permissions to Run Scripts
Let us see another example to restrict user access through SELinux.
By default, SELinux allows users mapped to the guest_t account to execute scripts from their home directories.
We can run the getsebool command to check the boolean value:
# getsebool allow_guest_exec_content
The output shows the flag is on.
guest_exec_content –> on
To verify its effect, we change the SELinux user mapping for the guestuser account.
In order to do that, run:
# semanage login -a -s guest_u guestuser
Then we verify the action:
# semanage login -l
As we can see, guestuser now maps to the guest_u SELinux user account.
Login Name SELinux User MLS/MCS Range Service __default__ unconfined_u s0-s0:c0.c1023 * guestuser guest_u s0 * regularuser user_u s0 * root unconfined_u s0-s0:c0.c1023 * system_u system_u s0-s0:c0.c1023 *
If we have an open terminal window as guestuser, we log out and log back as guestuser.
Next, we create an extremely simple bash script in the user’s home directory. The below code blocks first check the home directory, then creates the file and reads it on the console. Finally, the execute permission changes.
To verify we are in the guestuser home directory, we run:
[guestuser@localhost ~]$ pwd
/home/guestuser
Then we create the script:
[guestuser@localhost ~]$ vi myscript.sh
Script contents:
#!/bin/bash
echo “This is a test script”
Make the script executable:
# chmod u+x myscript.sh
When we try to execute the script as guestuser, it works:
[guestuser@localhost ~]$ ~/myscript.sh
This is a test script
Next, we go back to the root terminal window and change the boolean setting allow_guest_exec_content to off and verify it:
setsebool allow_guest_exec_content off
getsebool allow_guest_exec_content
guest\_exec\_content –> off
We go back to the console as guestuser and try to run the script again:
[guestuser@localhost ~]$ ~/myscript.sh
-bash: /home/guestuser/myscript.sh: Permission denied
So this is how SELinux can apply an additional layer of security on top of DAC.
In a production system, if we like them to access the server for viewing error messages and log files, and not to execute any shell scripts, we can first enable SELinux and then ensure the corresponding boolean value is set.
To see where this denial is, we can look at the /var/log/messages file.
Execute this from the root session:
# grep “SELinux is preventing” /var/log/messages
The last two messages in the file in our CentOS 7 server show the access denial:
Aug 23 12:59:42 localhost setroubleshoot: SELinux is preventing /usr/bin/bash from execute access on the file . For complete SELinux messages. run sealert -l 8343a9d2-ca9d-49db-9281-3bb03a76b71a Aug 23 12:59:42 localhost python: SELinux is preventing /usr/bin/bash from execute access on the file .
The message also shows a long ID value and suggests we run the sealert command with this ID for more information.
The following command shows this (use your own alert ID):
sealert -l 8343a9d2-ca9d-49db-9281-3bb03a76b71a
And indeed, the output gives us greater detail about the error:
SELinux is preventing /usr/bin/bash from execute access on the file . ***** Plugin catchall_boolean (89.3 confidence) suggests ****************** If you want to allow guest to exec content Then you must tell SELinux about this by enabling the ‘guest\_exec\_content’ boolean. You can read ‘None’ man page for more details. Do setsebool -P guest\_exec\_content 1 ***** Plugin catchall (11.6 confidence) suggests ************************** …
In the output note the lines at the beginning:
SELinux is preventing /usr/bin/bash from execute access on the file .
This gives us an idea of where the error is coming from.
Similarly, the next few lines also tell you how to fix the error:
If you want to allow guest to exec content Then you must tell SELinux about this by enabling the ‘guest\_exec\_content’ boolean. … setsebool -P guest\_exec\_content 1
SELinux in Action 3: Restrict Access to Services
Roles become important when dealing with users and processes.
Initially, we make sure that the httpd daemon is not running in the system. As the root user, to ensure this, we run:
# service httpd stop
Next, we switch to the terminal window we had logged in as a restricteduser and see the SELinux security context for it.
Start a new terminal session, if there isn’t one, against the system and log in as the restricteduser account:
[restricteduser@localhost ~]$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
The account has the default behavior of running as unconfined_u user and having access to unconfined_r role. However, it does not have the right to start any processes within the system.
The following code block shows that restricteduser is trying to start the httpd daemon and getting an access denied error:
[restricteduser@localhost ~]$ service httpd start Redirecting to /bin/systemctl start httpd.service Failed to issue method call: Access denied
Then, we move back to the root user terminal window and ensure the restricteduser account adds to the /etc/sudoers file.
This action will enable the restricteduser account to use root privileges.
# visudo
And then in the file, we add the following line, save and exit:
restricteduser ALL=(ALL) ALL
If we now log out of the restricteduser terminal window and log back in again, we can start and stop the httpd service with sudo privileges:
[restricteduser@localhost ~]$ sudo service httpd start
We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. [sudo] password for restricteduser: Redirecting to /bin/systemctl start httpd.service
The user can also stop the service:
[restricteduser@localhost ~]$ sudo service httpd stop
Redirecting to /bin/systemctl stop httpd.service
Suppose we want to stop this particular user from starting the httpd service even when the user’s account is listed in the sudoers file, we switch back to the root user’s terminal window and map the restricteduser to the SELinux user_r account.
# semanage login -a -s user_u restricteduser
Going back, we log out and log back in again in a new terminal session as restricteduser.
One done, we can verify its access using the seinfo command from our root user’s window:
seinfo -uuser_u -x
The output shows the roles user_u can assume. These are object_r and user_r:
user_u default level: s0 range: s0 roles: object_r user_r
We can run the seinfo command to check what domains the user_r role is authorized to enter:
seinfo -ruser_r -x
There are a number of domains user_r is authorized to enter:
user_r Dominated Roles: user_r Types: git_session_t sandbox_x_client_t git_user_content_t virt_content_t policykit_grant_t httpd_user_htaccess_t telepathy_mission_control_home_t qmail_inject_t gnome_home_t … …
We can try the same command with a filter:
seinfo -ruser_r -x | grep httpd
There are a number of httpd related domains the role has access to, but httpd_t is not one of them:
httpd_user_htaccess_t httpd_user_script_exec_t httpd_user_ra_content_t httpd_user_rw_content_t httpd_user_script_t httpd_user_content_t
Taking this example, if the restricteduser account tries to start the httpd daemon, the access should deny because the httpd process runs within the httpd_t domain and that is not one of the domains the user_r role is authorized to access.
In addition, we know user_u can assume the user_r role. This should fail even if the restricteduser account has been granted sudo privilege.
Going back to the restricteduser account’s terminal window, we try to start the httpd daemon:
[restricteduser@localhost ~]$ sudo service httpd start
The access is denied:
sudo: PERM_SUDOERS: setresuid(-1, 1, -1): Operation not permitted
SELinux users on CentOS 7 and Audit Logs
Generally, the error messages log in specific files and can provide details of access denials.
In a CentOS 7 system we can look at it in two files:
- /var/log/audit/audit.log
- /var/log/messages
The auditd daemon and the rsyslogd daemon respectively populates these files.
The /var/log/audit/audit.log file will be used if the auditd daemon is running and /var/log/messages file if auditd is stopped and rsyslogd is running.
However, if both are running, we use both. While /var/log/audit/audit.log records detailed information, an easy-to-read version is kept in /var/log/messages.
-
Deciphering Error Messages
We can use the grep command to sift through /var/log/messages file. Fortunately, SELinux comes with a few tools to make life a bit easier than that.
The first command is ausearch. We can make use of this command if the auditd daemon is running.
The following code looks at all the error messages related to the httpd daemon. We ensure we are in the root account:
ausearch -m avc -c httpd
It will list a number of entries, but we will concentrate on the last one:
—- time->Thu Aug 21 16:42:17 2014 … type=AVC msg=audit(1408603337.115:914): avc: denied { getattr } for pid=10204 comm=”httpd” path=”/www/html/index.html” dev=”dm-0″ ino=8445484 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file
If we look closely, the process domain is httpd_t and the file’s type context is default_t.
Since the httpd daemon runs within a confined domain and the SELinux policy stipulates this domain does not have any access to files with default_t type, the access was denied.
We can use the sealert command with the id value of the error message in the /var/log/messages file.
In the following command we grep through the /var/log/message file for SELinux related errors:
# cat /var/log/messages | grep “SELinux is preventing”
This error logs when the restricted user tries to run the httpd daemon:
… Aug 25 11:59:46 localhost setroubleshoot: SELinux is preventing /usr/bin/su from using the setuid capability. For complete SELinux messages. run sealert -l e9e6c6d8-f217-414c-a14e-4bccb70cfbce
As suggested, we ran sealert with the ID value and were able to see the details:
sealert -l e9e6c6d8-f217-414c-a14e-4bccb70cfbce
SELinux is preventing /usr/bin/su from using the setuid capability. … Raw Audit Messages type=AVC msg=audit(1408931985.387:850): avc: denied { setuid } for pid=5855 comm=”sudo” capability=7 scontext=user_u:user_r:user_t:s0 tcontext=user_u:user_r:user_t:s0 tclass=capability type=SYSCALL msg=audit(1408931985.387:850): arch=x86_64 syscall=setresuid success=no exit=EPERM a0=ffffffff a1=1 a2=ffffffff a3=7fae591b92e0 items=0 ppid=5739 pid=5855 auid=1008 uid=0 gid=1008 euid=0 suid=0 fsuid=0 egid=0 sgid=1008 fsgid=0 tty=pts2 ses=22 comm=sudo exe=/usr/bin/sudo subj=user_u:user_r:user_t:s0 key=(null) Hash: su,user_t,user_t,capability,setuid
Here, the first few lines of the output of sealert tell us about the remediation steps. However, if we look near the end of the output stream, we can see the “Raw Audit Messages” section.
The entry here is coming from the audit.log file, so we can use that section to help interpret the output here.
-
Multilevel Security
It is the fine-grained part of an SELinux security context.
So far we discussed, SELinux user, SELinux role, and SELinux type or domain. The fourth field of the security context shows the sensitivity and optionally, the category of the resource.
To understand it, let us consider the security context of the FTP daemon’s configuration file:
# ls -Z /etc/vsftpd/vsftpd.conf
This security context shows a sensitivity of s0.
-rw——-. root root system_u:object_r:etc_t:s0 /etc/vsftpd/vsftpd.conf
The sensitivity is part of the hierarchical multilevel security mechanism.
When an SELinux system uses MLS for its policy type, it marks certain files and processes with certain levels of sensitivity. The lowest level is “current sensitivity” and the highest level is “clearance sensitivity”.
Going hand-in-hand with sensitivity is the category of the resource. Categories are labels assigned to a resource. The purpose of categorization is to further fine-tune access control.
For example, we can mark certain files with confidential sensitivity for users from two different internal departments.
Here is an example of sensitivity/category pair:
user_u:object_r:etc_t:s0:c0.c2
Here, the only sensitivity level is s0. We can also write the category level as c0-c2.
Now, let us find the details from the /etc/selinux/targeted/setrans.conf file:
# cat /etc/selinux/targeted/setrans.conf
# # Multi-Category Security translation table for SELinux # # # Objects can be categorized with 0-1023 categories defined by the admin. # Objects can be in more than one category at a time. # Categories are stored in the system as c0-c1023. Users can use this # table to translate the categories into a more meaningful output. # Examples: # s0:c0=CompanyConfidential # s0:c1=PatientRecord # s0:c2=Unclassified # s0:c3=TopSecret # s0:c1,c3=CompanyConfidentialRedHat s0=SystemLow s0-s0:c0.c1023=SystemLow-SystemHigh s0:c0.c1023=SystemHigh
A process allows read access to a resource only when its sensitivity and category level are higher than that of the resource. The process can write to the resource when its sensitivity/category level is less than that of the resource.
[Need help with understanding SELinux? We can help you]
Conclusion
In short, we saw details of SELinux users on CentOS 7.
0 Comments