| name | apparmor-security |
| description | How to analyze, create, and test AppArmor security profiles on Linux systems. Use this skill whenever the user mentions AppArmor, Linux security profiles, Docker container security, mandatory access control (MAC), or needs to audit/modify program confinement policies. Also trigger when investigating privilege escalation paths, container escapes, or security hardening on Linux systems. |
AppArmor Security Analysis
A skill for analyzing, creating, and testing AppArmor security profiles on Linux systems.
What is AppArmor
AppArmor is a kernel enhancement that restricts program resources through per-program profiles, implementing Mandatory Access Control (MAC) by tying access control attributes directly to programs instead of users.
Key concepts:
- Profiles are loaded into the kernel (usually at boot)
- Profiles dictate what resources a program can access (network, files, sockets)
- Two modes: Enforcement (blocks violations) and Complain (logs violations only)
Quick Status Check
Start by checking what's currently confined:
sudo aa-status
This shows:
- How many profiles are loaded
- Which are in enforce mode vs complain mode
- Which binaries are restricted
Profile naming convention: Replace / with . in the binary path to find the profile file.
- Binary:
/usr/bin/man → Profile: /etc/apparmor.d/usr.bin.man
Core Commands
Status and Mode Management
aa-status
aa-enforce <profile>
aa-complain <profile>
Profile Management
apparmor_parser -a <profile>
apparmor_parser -C <profile>
apparmor_parser -r <profile>
apparmor_parser -R <profile>
Profile Creation Tools
aa-genprof <binary>
aa-easyprof <binary>
aa-logprof
aa-mergeprof
Creating Profiles
Method 1: Interactive Generation (aa-genprof)
This is the most thorough approach - AppArmor inspects actual binary behavior:
-
Start the generator:
sudo aa-genprof /path/to/binary
-
In a separate terminal, run the binary with typical operations:
/path/to/binary -a dosomething
-
Return to the generator terminal:
- Press
s to review recorded actions
- Use arrow keys to select: allow, deny, or ignore each action
- Press
f when finished to create the profile
The profile is saved to /etc/apparmor.d/path.to.binary
Method 2: Template Creation (aa-easyprof)
Quick template generation:
sudo aa-easyprof /path/to/binary
This creates a basic profile structure. Important: By default, nothing is allowed - you must explicitly add permissions:
"/path/to/binary" {
#include <abstractions/base>
/etc/passwd r, # Allow reading /etc/passwd
/var/log/myapp.log w, # Allow writing to log file
/usr/bin/helper ix, # Allow executing helper program
}
Access Control Modifiers
| Modifier | Meaning |
|---|
r | Read |
w | Write |
m | Memory map as executable |
k | File locking |
l | Create hard links |
ix | Execute with policy inheritance |
Px | Execute under another profile (cleaned env) |
Cx | Execute under child profile (cleaned env) |
Ux | Execute unconfined (cleaned env) |
Profile Variables
Use variables for flexibility:
#include <tunables/global>
"/path/to/binary" {
@{HOME}/** r, # Read from user's home directory
@{PROC}/** r, # Read from /proc
}
Analyzing Logs
Audit Log Format
AppArmor violations appear in /var/log/audit/audit.log:
type=AVC msg=audit(1610061880.392:287): apparmor="DENIED" \
operation="open" profile="/bin/rcat" name="/etc/hosts" \
pid=954 comm="service_bin" requested_mask="r" denied_mask="r"
Key fields:
operation: What action was attempted (open, getattr, etc.)
profile: Which AppArmor profile was active
name: Resource that was accessed
requested_mask: What access was requested (r=read, w=write, etc.)
denied_mask: What was actually denied
Interactive Log Review
sudo aa-notify -s 1 -v
Shows recent denials in a readable format:
Profile: /bin/service_bin
Operation: open
Name: /etc/passwd
Denied: r
Logfile: /var/log/audit/audit.log
AppArmor in Docker
Default Docker Profile
Docker uses docker-default profile by default. Key restrictions:
- ✅ Allowed: All networking access
- ❌ Denied: Writing to
/proc files
- ❌ Denied: Access to
/proc and /sys subdirectories
- ❌ Denied: Mount operations
- ⚠️ Limited: Ptrace only on processes with same profile
Important: AppArmor blocks capabilities even if granted. Example:
docker run -it --cap-add SYS_ADMIN ubuntu /bin/bash
echo "" > /proc/stat
Running with Custom Profile
docker run --rm -it --security-opt apparmor:myprofile ubuntu /bin/bash
Disabling AppArmor
docker run --rm -it --security-opt apparmor=unconfined ubuntu /bin/bash
Finding Container's Profile
docker inspect <container_id> | grep AppArmorProfile
find /etc/apparmor.d/ -name "*<profile_name>*" -maxdepth 1 2>/dev/null
Security Testing Considerations
Common Bypass Patterns
1. Path-based bypass: AppArmor is path-based. If /proc is protected but /host/proc is not:
docker run -v /proc:/host/proc ubuntu /bin/bash
2. Shebang bypass: Scripts with shebangs may execute under different profiles:
#!/usr/bin/perl
use POSIX qw(setuid);
POSIX::setuid(0);
exec "/bin/sh"
If you execute this script directly, it may run under the shell's profile, not perl's.
3. Profile modification: If you can modify and reload a profile:
sudo vim /etc/apparmor.d/docker-default
sudo apparmor_parser -r /etc/apparmor.d/docker-default
When Exploits Fail
If you have a privileged capability inside Docker but an exploit isn't working, AppArmor is likely blocking it. Check:
sudo aa-status | grep docker
Workflow Checklist
When analyzing AppArmor on a system:
- Check status:
sudo aa-status
- Identify target binary's profile: Find in
/etc/apparmor.d/
- Review profile contents:
cat /etc/apparmor.d/<profile>
- Check for denials:
sudo aa-notify -s 1 -v
- Test in complain mode:
sudo aa-complain <profile> (if you have access)
- Review audit logs:
grep apparmor /var/log/audit/audit.log
Troubleshooting
Profile not loading:
sudo apparmor_parser -C /etc/apparmor.d/<profile>
Binary not confined:
sudo aa-status | grep <binary_name>
Need to debug:
sudo aa-complain <profile>
sudo aa-notify -s 1 -v
sudo aa-enforce <profile>