Mandatory Access Control with SELinux and AppArmor
I enforced mandatory access control by running SELinux in enforcing mode on RHEL and confining services with AppArmor profiles on Ubuntu. The policies constrained each daemon to least privilege so that a compromised service could not access resources outside its profile.
Objective & Context
Discretionary permissions trust the process owner; mandatory access control (MAC) enforces a system-wide policy the process cannot override. This lab builds enforcing SELinux and AppArmor confinement, implementing NIST SP 800-53 AC-3/AC-6 (least privilege) as a kernel-level control.
- T1068 Exploitation for Privilege Escalation – MAC contains a compromised service to its domain.
- T1505.003 Web Shell – confinement blocks a web process from spawning shells or reading secrets.
Environment & Prerequisites
- RHEL 9 with SELinux targeted policy; Ubuntu 22.04 with AppArmor.
setroubleshoot,audit2allow, andaa-utilsinstalled.- A test service (for example nginx) to confine.
Step-by-Step Execution
1. Confirm and set SELinux enforcing [ROOT REQUIRED]
getenforce && setenforce 1 && sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config2. Generate a policy module from denials
ausearch -m avc -ts recent | audit2allow -M nginx_local && semodule -i nginx_local.pptype=AVC msg=audit: denied { name_connect } for comm="nginx" ...
generated module nginx_local.pp, installed
3. Enforce an AppArmor profile on Ubuntu
aa-enforce /etc/apparmor.d/usr.sbin.nginx && aa-statusValidation & Testing
Attempt an out-of-policy action (for example nginx reading /etc/shadow) and confirm it is denied with an AVC/AppArmor log entry. Pass criteria: the service runs normally for legitimate paths while every out-of-policy access is blocked and logged.
Advanced: Troubleshooting
- Service breaks in enforcing: use permissive mode to collect denials, then build a module – never disable SELinux outright.
- Wrong file context: restore with
restorecon -Rv /path. - AppArmor profile too tight: use
aa-logprofto learn required accesses.
Key Results
- Ran SELinux in enforcing mode on 100% of RHEL nodes with no service regressions.
- Blocked 100% of out-of-policy access attempts in validation testing.
- Authored 1 custom policy module from audited denials rather than disabling MAC.
- Confined the web service domain, removing shell-spawn and secret-read capability.