1

I've got a server that will have several applications on it, one of which is proprietary code, and another with the ability to examine files on the server due to the nature of our needs. This will not do. I'm trying to achieve per-vhost privilege separation to prevent one from examining the other. There are several mitigating circumstances which have complicated this...

  • CentOS8
  • Must use SELinux
  • Apache 2.4.37, PHP73, FCGI, PHP_FPM... using mpm_event
  • No mod_permissions, mod_itk/mpm_itk, mod_selinux modules out of the box on CentOS8

Since SELinux must be enabled in our case, and it also offers the best granularity for achieving our purposes, I've started down that path. In order to get it installed (from a Fedora Core 31 src) I followed these steps...

  1. dnf install httpd-devel selinux-policy-devel
  2. wget https://download.fedoraproject.org/pub/fedora/linux/releases/31/Everything/source/tree/Packages/m/mod_selinux-2.4.4-14.fc31.src.rpm
  3. rpmbuild --rebuild mod_selinux-2.4.4-14.fc31.src.rpm --define "_rpmdir /tmp"
  4. dnf install /tmp/x86_64/mod_selinux-2.4.4-14.el8.x86_64.rpm

This all went well, no errors, and everything was installed where it was supposed to be.

I have consolidated our serverwide settings into a single httpd.conf file rather than using lots of different conf files in conf.d (this is mostly due to simplicity when working with ansible templates and seeing everything in one place). NB: This does NOT include each of our vhost conf files / declarations which are still separate and included individually.

The default declaration for the httpd contexts is...

selinuxServerDomain    *:s0

I have 4x vhosts that I wish to compartmentalize, and I want to leave room for future expansion, so I adjusted that declaration to the following and added it to my httpd.conf file...

selinuxServerDomain    *:s0-s0:c0.c50

I then added the following to each of my vhost declarations respectively...

selinuxDomainVal *:s0:c10
selinuxDomainVal *:s0:c20
selinuxDomainVal *:s0:c30
selinuxDomainVal *:s0:c40

Lastly, I changed the context of the document roots on each of the respective vhost sites as follows...

chcon -R -l s0:c10 /var/www/site1
chcon -R -l s0:c20 /var/www/site2
chcon -R -l s0:c30 /var/www/site3
chcon -R -l s0:c40 /var/www/site4

Prior to using the context-sites, I was already successfully running the websites using the standard httpd related contexts (unconfined_u:object_r:httpd_sys_content_t, system_u:object_r:httpd_sys_rw_content_t), so I left them as is.

So the problem is, using the original *:s0 context, systemctl start httpd works fine, though none of the vhosts are accessible for the obvious reason that none of the spawned handlers are using the correct context.

However, when I change the context declaration to *:s0-s0:c0.c50, systemctl start httpd fails. status shows the following...

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/httpd.service.d
           └─php73-php-fpm.conf
   Active: failed (Result: exit-code) since Fri 2020-01-10 09:56:45 EST; 7s ago
     Docs: man:httpd.service(8)
  Process: 19362 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
 Main PID: 19362 (code=exited, status=1/FAILURE)
   Status: "Reading configuration..."

Jan 10 09:56:45 myhost.tld systemd[1]: Stopped The Apache HTTP Server.
Jan 10 09:56:45 myhost.tld systemd[1]: Starting The Apache HTTP Server...
Jan 10 09:56:45 myhost.tld systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
Jan 10 09:56:45 myhost.tld systemd[1]: httpd.service: Failed with result 'exit-code'.
Jan 10 09:56:45 myhost.tld systemd[1]: Failed to start The Apache HTTP Server.

There is no helpful info there I can see. Similarly journalctl -xe shows the same message lines, no additional help. The only thing I could find was in the error.log...

[Fri Jan 10 09:56:45.245476 2020] [core:notice] [pid 19362:tid 139989213628672] SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
[Fri Jan 10 09:56:45.253134 2020] [:error] [pid 19362:tid 139989213628672] (13)Permission denied: SELinux: setcon_raw("system_u:system_r:httpd_t:s0-s0:c0.c50") failed
AH00016: Configuration Failed

But due to my relative infancy when dealing with SEL policies, I'm not exactly sure what it's telling me. Can someone help shed some light on what I'm doing wrong here?

I've tried moving the context declaration up and down in the conf file just in case it was trying to set before another dependency but no change. I tried changing the context users from system_u to unconfined_u in the directory contexts and back again, no change. Not sure what else to try.

Thanks in advance for any help you can offer!


EDIT:

I've been able to get a little more specific info on the AVC Denial from the audit.log...

type=AVC msg=audit(1578928482.042:458750): avc:  denied  { setcurrent } for  pid=11335 comm="httpd" scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:system_r:httpd_t:s0 tclass=process permissive=0
type=SYSCALL msg=audit(1578928482.042:458750): arch=c000003e syscall=1 success=no exit=-13 a0=d a1=55e37564e5c0 a2=29 a3=0 items=0 ppid=1 pid=11335 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null)^]ARCH=x86_64 SYSCALL=write AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root"
type=PROCTITLE msg=audit(1578928482.042:458750): proctitle=2F7573722F7362696E2F6874747064002D44464F524547524F554E44
type=SERVICE_START msg=audit(1578928482.054:458751): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=httpd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=failed'^]UID="root" AUID="unset"

Does that help at all?

oucil
  • 445
  • 3
  • 16

1 Answers1

0

I'm answering this because I found the solution, however I don't quite understand what I've done, so if you can comment to provide clarity, I'm sure others will appreciate it as much as I would...

In order to get a bit more help translating the cryptic notes in the audit.log, I installed two utilities: setroubleshoot and setools

dnf install setroubleshoot setools

After they were in place, I ran the following to analyze the audit.log AVC errors...

sealert -a /var/log/audit/audit.log

The response was in english (vs giberish) and provided a helpful list of instructions for fixing the problem...

--------------------------------------------------------------------------------

SELinux is preventing /usr/sbin/httpd from using the setcurrent access on a process.

*****  Plugin catchall (100. confidence) suggests   **************************

If you believe that httpd should be allowed setcurrent access on processes labeled httpd_t 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:
# ausearch -c 'httpd' --raw | audit2allow -M my-httpd
# semodule -X 300 -i my-httpd.pp


Additional Information:
Source Context                unconfined_u:system_r:httpd_t:s0
Target Context                unconfined_u:system_r:httpd_t:s0
Target Objects                Unknown [ process ]
Source                        httpd
Source Path                   /usr/sbin/httpd
Port                          <Unknown>
Host                          <Unknown>
Source RPM Packages           httpd-2.4.37-12.module_el8.0.0+185+5908b0db.x86_64
Target RPM Packages
Policy RPM                    selinux-policy-3.14.1-61.el8_0.2.noarch
Selinux Enabled               True
Policy Type                   targeted
Enforcing Mode                Enforcing
Host Name                     ##REMOVEDFORPRIVACY###
Platform                      Linux ##REMOVEDFORPRIVACY###
                              4.18.0-80.11.2.el8_0.x86_64 #1 SMP Tue Sep 24
                              11:32:19 UTC 2019 x86_64 x86_64
Alert Count                   1
First Seen                    2020-01-09 18:02:47 EST
Last Seen                     2020-01-09 18:02:47 EST
Local ID                      22e251b9-72fc-42a1-875b-0db3ab095f9d

Raw Audit Messages
type=AVC msg=audit(1578610967.597:455070): avc:  denied  { setcurrent } for  pid=11650 comm="httpd" scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:system_r:httpd_t:s0 tclass=process permissive=0


type=SYSCALL msg=audit(1578610967.597:455070): arch=x86_64 syscall=write success=no exit=EACCES a0=c a1=56494ec9d5d0 a2=2c a3=0 items=0 ppid=11648 pid=11650 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=959 comm=httpd exe=/usr/sbin/httpd subj=unconfined_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=write AUID=ecms UID=root GID=root EUID=root SUID=root FSUID=root EGID=root SGID=root FSGID=root

Hash: httpd,httpd_t,httpd_t,process,setcurrent

--------------------------------------------------------------------------------

The solution was to run the commands suggested...

ausearch -c 'httpd' --raw | audit2allow -M my-httpd
semodule -X 300 -i my-httpd.pp

After which I was able to finally restart Apache.

So it's pretty clear that in following the above, I created a custom policy for the httpd service, but that's about all I understand. The commands do not mention the setcurrent command/permission which was referenced in the error report, and there's no output from either command with any extra info. I'm assuming that the ausearch on the term httpd piped into audit2allow essentially uses the error report to generate the custom policy, but would love to understand exactly what happened, and where that custom policy is now stored on the system.

Hope this helps, and thanks if you can provide any helpful explanation as to why!

oucil
  • 445
  • 3
  • 16