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, and aa-utils installed.
  • 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/config

2. Generate a policy module from denials

ausearch -m avc -ts recent | audit2allow -M nginx_local && semodule -i nginx_local.pp
type=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-status

Validation & 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-logprof to 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.