AppArmor¶
AppArmor is Ubuntu's mandatory access control (MAC) system. It confines programs to a limited set of resources, reducing the damage from compromised applications.
Understanding AppArmor¶
What AppArmor Does¶
┌─────────────────────────────────────────────────────────────┐
│ Application Request │
│ (e.g., read /etc/passwd) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ AppArmor Policy Check │
│ │
│ Profile: /usr/sbin/nginx │
│ Rule: /etc/passwd r, ← Read allowed │
│ Rule: /etc/shadow deny, ← Explicitly denied │
│ │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────┴─────────────────┐
│ │
▼ ▼
┌─────────┐ ┌─────────┐
│ Allowed │ │ Denied │
│ Access │ │ + Log │
└─────────┘ └─────────┘
AppArmor vs SELinux¶
| Feature | AppArmor | SELinux |
|---|---|---|
| Default in | Ubuntu, SUSE | RHEL, Fedora |
| Policy style | Path-based | Label-based |
| Complexity | Lower | Higher |
| Learning curve | Easier | Steeper |
| Flexibility | Good | Very high |
Profile Modes¶
| Mode | Behavior |
|---|---|
| Enforce | Policy enforced, violations blocked and logged |
| Complain | Policy not enforced, violations only logged |
| Disabled | Profile not loaded |
Check AppArmor Status¶
System Status¶
# Check if AppArmor is enabled
sudo aa-status
# Or shorter
sudo apparmor_status
# Output shows:
# - Number of loaded profiles
# - Profiles in enforce/complain mode
# - Processes with profiles
Service Status¶
# AppArmor service
sudo systemctl status apparmor
# Verify kernel support
cat /sys/module/apparmor/parameters/enabled
# Should output: Y
Managing Profiles¶
Profile Locations¶
| Location | Purpose |
|---|---|
/etc/apparmor.d/ | Main profiles |
/etc/apparmor.d/local/ | Local customizations |
/etc/apparmor.d/disable/ | Disabled profiles (symlinks) |
/etc/apparmor.d/abstractions/ | Common rule sets |
/etc/apparmor.d/tunables/ | Variables |
List Profiles¶
# All profiles
ls /etc/apparmor.d/
# Profiles by status
sudo aa-status --enabled
sudo aa-status --profiled
Profile Operations¶
# Reload all profiles
sudo systemctl reload apparmor
# Reload specific profile
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
# Set profile to enforce mode
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
# Set profile to complain mode
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
# Disable profile
sudo aa-disable /etc/apparmor.d/usr.sbin.nginx
# Remove profile from kernel
sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.nginx
Profile Syntax¶
Basic Structure¶
# /etc/apparmor.d/usr.bin.example
#include <tunables/global>
profile example /usr/bin/example {
#include <abstractions/base>
# Allow reading own binary
/usr/bin/example mr,
# Allow reading config
/etc/example.conf r,
# Allow writing logs
/var/log/example.log w,
# Deny access to sensitive files
deny /etc/shadow r,
}
Permission Flags¶
| Flag | Permission |
|---|---|
r | Read |
w | Write |
a | Append |
x | Execute (inherit profile) |
ix | Execute (inherit profile) |
px | Execute (transition to profile) |
Px | Execute (transition or fail) |
ux | Execute (unconfined) |
cx | Execute (child profile) |
m | Memory map executable |
k | File locking |
l | Link |
Common Patterns¶
# Exact path
/path/to/file r,
# Wildcard - single directory component
/path/to/dir/* r,
# Recursive - all subdirectories
/path/to/dir/** r,
# Pattern matching
/var/log/*.log w,
/home/*/.config r,
# Owner condition
owner /home/*/.ssh/* r,
# Deny explicitly
deny /etc/shadow r,
Abstractions¶
Abstractions provide common rule sets:
# Include common patterns
#include <abstractions/base> # Basic system access
#include <abstractions/nameservice> # DNS, passwd lookups
#include <abstractions/openssl> # SSL/TLS libraries
#include <abstractions/ssl_certs> # Certificate files
#include <abstractions/python> # Python interpreter
Available in /etc/apparmor.d/abstractions/.
Creating Custom Profiles¶
Generate Profile with aa-genprof¶
# Install utilities
sudo apt install apparmor-utils
# Generate profile interactively
sudo aa-genprof /usr/bin/myapp
Then: 1. Run myapp in another terminal 2. Exercise all functionality 3. Return to aa-genprof and press 'S' to scan logs 4. Accept/deny actions as prompted 5. Press 'F' to finish
Generate Profile with aa-autodep¶
# Create basic profile
sudo aa-autodep /usr/bin/myapp
# Profile created at /etc/apparmor.d/usr.bin.myapp
# Start in complain mode
sudo aa-complain /etc/apparmor.d/usr.bin.myapp
# Run application, then check logs
sudo aa-logprof
Manual Profile Creation¶
# /etc/apparmor.d/usr.local.bin.myapp
#include <tunables/global>
profile myapp /usr/local/bin/myapp {
#include <abstractions/base>
#include <abstractions/nameservice>
# Binary
/usr/local/bin/myapp mr,
# Libraries
/usr/lib/** mr,
/lib/x86_64-linux-gnu/** mr,
# Configuration
/etc/myapp/ r,
/etc/myapp/** r,
# Data
/var/lib/myapp/ rw,
/var/lib/myapp/** rw,
# Logs
/var/log/myapp/ rw,
/var/log/myapp/** w,
# PID file
/var/run/myapp.pid rw,
# Network
network inet stream,
network inet dgram,
# Deny sensitive areas
deny /etc/shadow r,
deny /root/** rw,
}
Load profile:
Network Rules¶
Network Access Control¶
# Allow specific network types
network inet stream, # TCP over IPv4
network inet dgram, # UDP over IPv4
network inet6 stream, # TCP over IPv6
network unix stream, # Unix sockets
# Deny all network
deny network,
Capability Rules¶
Linux Capabilities¶
# Allow specific capabilities
capability net_bind_service, # Bind to ports < 1024
capability chown, # Change file ownership
capability dac_override, # Bypass permission checks
capability setuid, # Set UID
capability setgid, # Set GID
# Deny all capabilities
deny capability,
Debugging and Troubleshooting¶
View Denials¶
# Real-time denials
sudo dmesg -w | grep apparmor
# From audit log
sudo grep apparmor /var/log/audit/audit.log
# From syslog
sudo grep apparmor /var/log/syslog
# Parse and display denials
sudo aa-notify -s 1 -v
Analyze Denials¶
# Interactive profile update
sudo aa-logprof
# This reads recent denials and offers to:
# - Add rules to profiles
# - Set permissions
# - Update abstractions
Common Issues¶
Application fails with "Permission denied":
# Check if confined
sudo aa-status | grep <process>
# Look for denials
sudo dmesg | grep -i apparmor | grep DENIED
# Temporarily set to complain mode
sudo aa-complain /etc/apparmor.d/profile
# Run application, then analyze
sudo aa-logprof
Profile not loading:
# Check syntax
sudo apparmor_parser -p /etc/apparmor.d/profile
# View errors
sudo apparmor_parser -r /etc/apparmor.d/profile 2>&1
Example Profiles¶
Nginx Web Server¶
# /etc/apparmor.d/usr.sbin.nginx
#include <tunables/global>
profile nginx /usr/sbin/nginx {
#include <abstractions/base>
#include <abstractions/nameservice>
#include <abstractions/openssl>
# Binary
/usr/sbin/nginx mr,
# Libraries
/usr/lib/nginx/modules/** mr,
# Configuration
/etc/nginx/ r,
/etc/nginx/** r,
# SSL certificates
/etc/ssl/certs/** r,
/etc/ssl/private/** r,
# Web content (adjust path as needed)
/var/www/** r,
# Logs
/var/log/nginx/ rw,
/var/log/nginx/** w,
# PID and lock
/run/nginx.pid rw,
/var/lib/nginx/ rw,
/var/lib/nginx/** rw,
# Temp files
/var/cache/nginx/ rw,
/var/cache/nginx/** rw,
# Network
capability net_bind_service,
network inet stream,
network inet6 stream,
# Worker processes
capability setuid,
capability setgid,
capability dac_override,
}
Custom Application¶
# /etc/apparmor.d/local/usr.local.myapp
#include <tunables/global>
profile myapp /usr/local/bin/myapp flags=(attach_disconnected) {
#include <abstractions/base>
#include <abstractions/nameservice>
# Own binary
/usr/local/bin/myapp mr,
# Config
/etc/myapp.conf r,
# Data directory
owner /var/lib/myapp/ rw,
owner /var/lib/myapp/** rw,
# Logs
/var/log/myapp.log w,
# Temporary files
/tmp/myapp.* rw,
# Network (restrict to localhost)
network inet stream,
network inet dgram,
# Deny sensitive
deny /etc/shadow r,
deny /etc/gshadow r,
deny /root/** rw,
deny /home/** rw,
}
Local Customizations¶
Override Without Modifying Package Profiles¶
# Local additions for nginx
# Include from main profile with:
# #include <local/usr.sbin.nginx>
# Allow additional content directory
/srv/www/** r,
Add include to main profile:
Ubuntu Default Profiles¶
Ubuntu includes profiles for many applications:
# View installed profiles
dpkg -L apparmor-profiles
dpkg -L apparmor-profiles-extra
# Install additional profiles
sudo apt install apparmor-profiles apparmor-profiles-extra
Common default profiles:
| Application | Profile Status |
|---|---|
| Firefox | Shipped but not enabled |
| LibreOffice | Shipped but not enabled |
| cups-browsed | Enabled |
| man | Enabled |
| tcpdump | Enabled |
Best Practices¶
Profile Development¶
- Start in complain mode
- Exercise all application functionality
- Use aa-logprof to add necessary rules
- Review and minimize permissions
- Test in enforce mode
- Monitor for denials
Security Guidelines¶
| Practice | Reason |
|---|---|
| Use abstractions | Consistent, maintained rule sets |
| Minimize permissions | Only allow what's needed |
| Use owner keyword | Restrict to file owner |
| Deny sensitive explicitly | Document security intentions |
| Audit deny rules | Log denied access attempts |
Maintenance¶
# After package updates, reload profiles
sudo systemctl reload apparmor
# Periodically check for denials
sudo aa-notify -s 7 -v
# Review and update profiles
sudo aa-logprof
Quick Reference¶
Commands¶
# Status
sudo aa-status
sudo apparmor_status
# Profile management
sudo aa-enforce /path/to/profile
sudo aa-complain /path/to/profile
sudo aa-disable /path/to/profile
# Profile generation
sudo aa-genprof /path/to/binary
sudo aa-logprof
# Reload
sudo systemctl reload apparmor
sudo apparmor_parser -r /path/to/profile
# Debugging
sudo dmesg | grep apparmor
sudo aa-notify -s 1 -v
Next Steps¶
Continue to Fail2ban to set up intrusion prevention.