Frontend Labs
⋯

Chapter 71 -- Linux security hardening: SELinux/AppArmor, auditd, capabilities, and least privilege

In one sentence

Linux hardening is layered least privilege: reduce what a process can read, write, execute, call, bind, load, and persist, while keeping enough observability to detect when those boundaries are tested.

Why this matters

Unix permissions are necessary but not sufficient. Real services also need service accounts, limited sudo, capabilities instead of root, syscall filters, MAC policy, secret handling, patching, logging, and a way to prove the controls are working.

How it actually works

Hardening layers:

   identity        dedicated user/group, no shared admin account
   filesystem      ownership, mode bits, mount options, read-only paths
   privilege       sudoers scope, Linux capabilities, no_new_privs
   isolation       systemd sandboxing, namespaces, containers, chroot where useful
   MAC             SELinux or AppArmor policy
   kernel          seccomp, module loading rules, exploit mitigations
   audit           auditd/journald/SIEM events tied to real questions

Useful inspection:

id myapp 2>/dev/null || true
getcap -r /usr/bin /usr/sbin 2>/dev/null
sudo -l
aa-status 2>/dev/null || true
getenforce 2>/dev/null || true
systemctl show myapp.service -p NoNewPrivileges -p CapabilityBoundingSet 2>/dev/null

Real-world scenario

A web service runs as root only because it binds port 80. Better options:

   - put a reverse proxy/load balancer in front;
   - bind a high port and let the proxy listen on 80/443;
   - grant only CAP_NET_BIND_SERVICE to the binary, if appropriate;
   - use systemd socket activation.

The expert question is not "can I make it work?" It is "what is the smallest privilege that makes it work, and how will I notice if it tries to exceed that?"

Try it yourself

In a lab, compare a service run as your user, as root, and as a dedicated service account. List the files it can write and the ports it can bind. Then remove one privilege and observe the failure mode in logs.

Common mistakes

  • Disabling SELinux/AppArmor because of one denial instead of understanding the denial and adjusting policy or application behaviour.
  • Giving NOPASSWD: ALL in sudoers for convenience.
  • Running containers as root and assuming "container" means "safe."
  • Collecting audit logs without a detection question.

Check yourself

  1. Why are Linux capabilities safer than full root for narrow privileges?
  2. What problem do SELinux/AppArmor solve that mode bits do not?
  3. Why is logging a hardening control only when someone reviews or alerts on it?

Across the series

  • The attacker's view of these controls: Security Engineering in Depth covers container internals and escapes (Chapter 15), Kubernetes RBAC, admission, network, and runtime security (Chapters 17–20), with a Go lab for workload identity over mTLS (Chapter 23).
  • Hardening applied to one service: the systemd unit and Kubernetes manifest in Chapter 82 (exposure score 3.1 vs 9.6 unhardened).

Generated from real-life-os-guide.md · 8 Oct 2026 16:36