Lion Cipher Lab
Allowlist what can run: deny-by-default execution control with fapolicyd
- Cyber / Security Engineer
- Advanced
- ~75 min
- Free · no account required
Why it matters
Antivirus is allow-by-default: a program runs unless a signature says otherwise, which means a binary the vendor has never seen -- a fresh malware dropper, a living-off-the-land tool an attacker dropped in /tmp, a ransomware stage two -- runs first and gets caught later, if ever. Application allowlisting inverts that: nothing executes unless it is on a list of known-good software, so the novel binary is denied precisely BECAUSE it is unknown. NIST wrote a whole guide about this control (SP 800-167) because on a machine whose software set is stable -- a server, a kiosk, an OT box --…
What you'll learn
- the allow-by-default vs deny-by-default mental model: why signature AV misses a novel binary and application allowlisting does not (NIST SP 800-167)
- installing and running fapolicyd on a RHEL-family box, and understanding it is fanotify-based execution control, not antivirus
- the TRUST DATABASE: rpm-backed trust (every file a package installed) plus the file trust list (fapolicyd-cli --file add), and reading trust=1 vs trust=0
- the rules.d policy model: decision (allow/deny_audit) + perm=execute|open + subject : object + trust, and why rule ORDER and the final deny matter
- running PERMISSIVE first and watching decisions with fapolicyd --debug-deny, then flipping to ENFORCING without locking yourself out
- proving the control bites: a binary you compiled in /tmp is denied with 'Operation not permitted' and a fapolicyd deny_audit line, while trusted binaries still run
- adding a vetted binary to trust (fapolicyd-cli --file add + --update) and watching the same binary go from denied to allowed
- the INTERPRETER BYPASS: a trusted interpreter runs an untrusted script because the script is OPENED not executed -- so you must control perm=open on interpreted content, not just perm=execute
- tuning false positives after updates: dnf changes a file's hash, fapolicyd-cli --file update / the dnf plugin keep trust honest, and integrity modes none/size/sha256/ima trade safety for cost
- the judgment: allowlisting vs SELinux/AppArmor (orthogonal) and vs IMA/EVM, and where the operational cost is worth it versus a nightmare
Steps in this lab
- The threat: allow-by-default AV vs deny-by-default allowlisting
- Spin up a RHEL-family box and install fapolicyd (honest platform note)
- Understand the TRUST DATABASE: rpm-backed trust + the file trust list
- Read the RULES model: decision, perm, subject : object, and trust
- PERMISSIVE first: run the daemon in the foreground and watch decisions
- Build the benign stand-in: compile a 'hello' binary in /tmp
- PROVE it bites: flip to ENFORCING and get denied, read the deny line
- Add it to trust and watch it run: fapolicyd-cli --file add + --update
- The INTERPRETER BYPASS: why execute-only control has a hole
- Tune FALSE POSITIVES: updates change hashes, integrity modes, trust-source order
- The judgment: allowlisting vs SELinux/AppArmor and IMA, and when it's worth it