SELinux is a complex beast that the average administrator will never fully understand or tame. That said, it is a very important security tool that we need to learn to live with. The good news is that all the heavy lifting of configuring the policy used to protect our system is done for us by the RedHat/CentOS teams. All we need to do is learn how to live in harmony with this powerful guard dog.
In this lab we will learn how to recognize and remedy some of the most common headaches SELinux gives admins. This lab will not make you and SELinux expert. It should give you the skills to turn SELinux on without breaking into a cold sweat.
It is recommended that you review the Security-Enhanced Linux Users Guide found on the redhat documentation site.
We will use earth from previous lab.
mkdir /web cp /var/www/html/1.html /web
ln -s /web /var/www/html/web
The main purpose of the SELinux targeted policy is to ensure that certain key system processes, like httpd, are only allowed to access resources, like files and ports, that are safe. If an attacker takes control of the httpd daemon process, we do not want them to be able to look around the file system. SELinux limits the access of httpd to files with specific SELinux types. Let's see how that works..
curl http://localhost/1.html
curl http://localhost/web/1.html
ll -l /web ll -ld /webThat can't be the problem both are world readable.
tail /var/log/httpd/error_logit will show something like..
[Fri Dec 30 15:21:01.144450 2022] [core:error] [pid 1202:tid 140093408352000] (13)Permission denied: [client ::1:51638] AH00035: access to /web/1.html denied (filesystem path '/var/www/html/web/1.html') because search permissions are missing on a component of the pathAs we expected httpd can't access /web, but we get no additional hint as to why. This is where an admin unfamiliar with SELinux is likely to become perplexed.
grep AVC /var/log/audit/audit.logshould show something like...
type=AVC msg=audit(1672431661.143:124): avc: denied { getattr } for pid=1202 comm="httpd" path="/web/1.html" dev="dm-0" ino=87 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=0This tells us that SELinux has intervened. This tutorial will give a little more detail. (Archived version)
Field | Tells us |
comm="httpd" | Offending executable. |
path="/web" | Resource that was denied |
scontext=system_u:system_r:httpd_t:s0 | The source context, or "who SELinux thinks is asking" |
tcontext=system_u:object_r:default_t:s0 | The target context, or "what SELinux thinks is being asked for" |
ls -lZ /var/www/html/1.html ps -eflZ |grep httpd id -Z
A comparison of /web/1.html and /var/www/html/1.html will show us what needs to change.
Consider the results of these commands...[root@tina ~]# ll -Z /var/www/html/1.html rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 38 Dec 30 15:14 /var/www/html/1.html [root@tina ~]# ll -Z /web/1.html -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 38 Dec 30 15:14 /web/1.htmlWe can see that the only difference between these two files, from an SELinux viewpoint, is that they have different types. If we could get /web/1.html to have the same type, httpd_sys_content_t, as /var/www/html/1.html, all would be good. We have two ways of changing this type. One will survive a re-labeling, and one will not. Either will survive a reboot.
chcon -Rv -t httpd_sys_content_t /web
You may recall that when we switched SELinux to enforcing mode it took a while for the system to boot. This was because the mode change triggered a full file system relabeling. The context of a file is stored in the file system as an extended attribute. But it is the SELinux policy, targeted in our case, that defines what the context of any given file should be. The targeted policy says that /web and everything below it shoud have a type of default_t. If a full file system relabeling is triggered /web and all it's contents will revert to a type of default_t and no longer be accessible to httpd.
If we want to make /web available to httpd on a truly permanent basis, we should modify the targeted policy telling it "/web should have a type of httpd_sys_content_t.
restorecon -Rv /web
curl http://localhost/web/1.html
yum install policycoreutils-python-utils
semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
restorecon -Rv /web
curl http://localhost/web/1.html
SELinux can restrict access to ports just like it restricts access to files. In this section we will make earth listen on port 9317.
semanage port -l|grep http
Listen 9317
semanage port -a -t http_port_t -p tcp 9317
curl http://localhost:9317/1.html