dotlinux guide

Dive into the Linux Security Model: Theory and Practice

Linux, the backbone of modern computing infrastructure—powering servers, cloud environments, embedded systems, and even mobile devices—relies on a robust security model to protect against evolving threats. Unlike monolithic security systems, Linux’s security architecture is a layered, modular framework designed to enforce access control, minimize attack surfaces, and protect critical resources. Whether you’re a system administrator securing a production server, a developer hardening an application, or a security enthusiast exploring Linux internals, understanding this model is foundational to building resilient systems. This blog will demystify the Linux security model, starting with core theoretical concepts like Discretionary Access Control (DAC) and progressing to advanced mechanisms like Mandatory Access Control (MAC). We’ll explore practical tools, common pitfalls, and best practices, with hands-on code examples to bridge theory and real-world application. By the end, you’ll have a clear roadmap to secure Linux systems effectively.

Table of Contents

  1. Overview of the Linux Security Model
  2. Fundamental Concepts
  3. Advanced Security: Mandatory Access Control (MAC)
  4. Practical Usage and Commands
  5. Common Security Practices
  6. Best Practices for Linux Security
  7. Code Examples and Demos
  8. Conclusion
  9. References

Overview of the Linux Security Model

The Linux security model is built on the principle of least privilege—no user or process should have more access than necessary to perform its function. It combines multiple layers of defense, including:

  • Discretionary Access Control (DAC): The traditional “user/group/others” permission model, where resource owners define access rules.
  • Mandatory Access Control (MAC): Policy-driven enforcement that restricts access based on system-wide rules, regardless of user intent.
  • Capabilities: Fine-grained privilege separation to avoid over-reliance on the all-powerful root user.
  • Auditing and Logging: Tools to track and investigate security events.

This layered approach ensures that even if one defense is bypassed, others remain to mitigate risk.

Fundamental Concepts

Discretionary Access Control (DAC)

DAC is the cornerstone of Linux security, where access to files, processes, and network resources is controlled by the owner of the resource. Ownership is determined by user IDs (UIDs) and group IDs (GIDs).

Users, Groups, and UIDs/GIDs

Every Linux user has a unique UID (e.g., root is UID 0), and belongs to one or more groups (GIDs). Key files managing users and groups include:

  • /etc/passwd: Stores user account details (UID, home directory, shell).
  • /etc/group: Defines group memberships.
  • /etc/shadow: Securely stores hashed passwords (readable only by root).

Linux File Permissions

Every file/directory has permissions for three entities:

  • User (u): The owner of the file.
  • Group (g): The group associated with the file.
  • Others (o): All other users on the system.

Permissions are represented by 10 bits (visible via ls -l):

  • 1st bit: File type (e.g., - for regular file, d for directory).
  • Next 3 bits: User permissions (rwx).
  • Next 3 bits: Group permissions (rwx).
  • Next 3 bits: Others permissions (rwx).

Example output of ls -l secret.txt:

-rw-r----- 1 alice devteam 4096 Jun 1 12:00 secret.txt
  • -: Regular file.
  • rw-: User (alice) can read/write.
  • r--: Group (devteam) can read.
  • ---: Others have no access.

Permissions are modified with chmod (change mode) and ownership with chown (change owner). Numeric notation (e.g., chmod 600 file) is common, where each permission is a value: r=4, w=2, x=1.

SUID, SGID, and Sticky Bits

Special permission bits extend DAC:

  • SUID (Set User ID): When a file with SUID is executed, it runs with the owner’s UID (not the executor’s). Example: /bin/passwd (owned by root) allows users to modify /etc/shadow.
    ls -l /bin/passwd
    -rwsr-xr-x 1 root root 68208 Jun 1 2023 /bin/passwd  # 's' in user x position = SUID
  • SGID (Set Group ID): Similar to SUID, but runs with the group’s GID. Useful for shared directories (e.g., /var/www for a web server group).
  • Sticky Bit: On directories (e.g., /tmp), prevents users from deleting files they don’t own.
    ls -ld /tmp
    drwxrwxrwt 10 root root 4096 Jun 1 12:00 /tmp  # 't' in others x position = sticky bit

Warning: SUID/SGID can introduce risks if misconfigured (e.g., a SUID binary with a vulnerability allows privilege escalation). Audit them with find / -perm -4000 2>/dev/null (SUID) or -2000 (SGID).

Linux Capabilities

The root user (UID 0) has unlimited privileges, but this “all-or-nothing” model is risky. Capabilities split root privileges into granular units, allowing processes to run with only the privileges they need.

Common capabilities:

  • CAP_NET_BIND_SERVICE: Bind to ports < 1024 (e.g., port 80/443 for a web server).
  • CAP_SYS_ADMIN: “Super admin” (avoid unless necessary).
  • CAP_DAC_OVERRIDE: Bypass file read/write/execute permissions.
  • CAP_KILL: Send signals to processes of other users.

Manage capabilities with setcap (set) and getcap (query):

# Allow a Node.js app to bind to port 80 without root
sudo setcap 'cap_net_bind_service=+ep' /usr/bin/node

# Verify
getcap /usr/bin/node
/usr/bin/node cap_net_bind_service=ep

Best Practice: Use capabilities instead of SUID for privilege separation.

Advanced Security: Mandatory Access Control (MAC)

Limitations of DAC

DAC relies on user-defined permissions, which can be bypassed (e.g., a compromised user can modify their own file permissions). MAC enforces system-wide policies that restrict access regardless of ownership, adding a critical layer beyond DAC.

SELinux

Security-Enhanced Linux (SELinux), developed by the NSA, uses labels and policies to enforce MAC. Every process, file, and network resource has a security label (e.g., system_u:object_r:httpd_t:s0), and policies define allowed label interactions.

Key SELinux Concepts:

  • Labels: Format: user:role:type:level (e.g., unconfined_u:unconfined_r:unconfined_t:s0 for a regular user process).
  • Policies: Rules defining allowed actions (e.g., “httpd_t processes can read httpd_sys_content_t files”).
  • Modes:
    • Enforcing: Deny access violating policy (default on RHEL/CentOS).
    • Permissive: Log violations but don’t block (for testing).
    • Disabled: SELinux inactive.

Basic SELinux Management:

# Check status
sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing

# View file labels
ls -Z /var/www/html/index.html
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html

# Restore default label (if mislabeled)
restorecon -v /var/www/html/index.html

# Troubleshoot: Convert audit logs to policy allow rules
audit2allow -a  # Reads /var/log/audit/audit.log

AppArmor

AppArmor (Application Armor), used by Ubuntu, SUSE, and Debian, is a simpler MAC alternative to SELinux. It uses path-based profiles to restrict applications to predefined file paths and system calls.

Key AppArmor Concepts:

  • Profiles: Text files defining allowed paths (e.g., /usr/bin/nginx can read /var/www but not /etc/shadow).
  • Modes:
    • Enforce: Block access violating the profile.
    • Complain: Log violations but don’t block (for profiling).

Basic AppArmor Management:

# Check status
aa-status
apparmor module is loaded.
6 profiles are loaded.
6 profiles are in enforce mode.

# Create a profile for a custom app (interactive)
sudo aa-genprof /usr/bin/myapp

# Edit a profile
sudo nano /etc/apparmor.d/usr.bin.myapp

# Enforce/complain mode
sudo aa-enforce /usr/bin/myapp
sudo aa-complain /usr/bin/myapp

Example AppArmor profile for a web app:

# /etc/apparmor.d/usr.bin.myapp
/usr/bin/myapp {
  # Allow read access to config
  /etc/myapp/config.conf r,
  # Allow read/write to logs
  /var/log/myapp/*.log rw,
  # Deny access to sensitive files
  /etc/shadow r denied,
}

Practical Usage and Commands

Managing File Permissions

# Restrict a private key to owner-only read/write
chmod 600 ~/.ssh/id_rsa

# Make a script executable for owner/group
chmod 750 script.sh

# Change owner/group of a file
chown alice:devteam project.doc

User/Group Management

# Create a new user with home directory
sudo useradd -m -s /bin/bash newuser
sudo passwd newuser

# Add user to a group (e.g., sudo for admin rights)
sudo usermod -aG sudo newuser

# List groups a user belongs to
groups newuser

Capabilities

# Remove CAP_NET_BIND_SERVICE from Node.js
sudo setcap -r /usr/bin/node

# List capabilities for all binaries
getcap -r / 2>/dev/null

SELinux Policy Adjustment

# Allow Apache to connect to a database (common web app scenario)
sudo semanage permissive -a httpd_t  # Temporarily permissive
# (Trigger the connection, then generate policy)
sudo audit2allow -a -M httpd_db_connect
sudo semodule -i httpd_db_connect.pp  # Load the new policy

AppArmor Profile Debugging

# View AppArmor logs for a profile
sudo grep myapp /var/log/syslog | grep apparmor

Common Security Practices

Least Privilege Principle

  • Avoid using root for daily tasks; use sudo for admin actions.
  • Run services (e.g., Nginx, PostgreSQL) as non-root users (e.g., www-data, postgres).
  • Restrict sudo access with /etc/sudoers (use visudo to edit safely).

Regular Updates and Patching

# Debian/Ubuntu
sudo apt update && sudo apt upgrade -y

# RHEL/CentOS
sudo dnf update -y

Enable automatic updates with unattended-upgrades (Debian) or dnf-automatic (RHEL).

Auditing and Logging

  • Use auditd to monitor file access, process execution, and privilege changes:
    sudo apt install auditd
    sudo auditctl -w /etc/passwd -p wa  # Log writes/appends to passwd
  • Check logs with journalctl (systemd) or /var/log/auth.log (auth events).

Firewall Configuration

  • Block unnecessary ports with ufw (Uncomplicated Firewall):
    sudo ufw allow 22/tcp  # Allow SSH
    sudo ufw allow 80/tcp  # Allow HTTP
    sudo ufw enable
    sudo ufw status

Best Practices for Linux Security

System Hardening

  • Use tools like lynis to audit and harden systems:
    sudo apt install lynis
    sudo lynis audit system
  • Follow CIS Benchmarks for industry-standard hardening guidelines.

Enforce MAC

  • Run SELinux/AppArmor in enforcing mode (never disabled in production).
  • Use vendor-provided policies (e.g., RHEL’s SELinux policies for Apache) instead of custom rules when possible.

Container Security

  • Use rootless containers (Podman, Docker rootless mode) to avoid container-to-host privilege escalation.
  • Restrict system calls with seccomp (e.g., Docker’s --security-opt seccomp=profile.json).

File Integrity Monitoring (FIM)

  • Tools like AIDE (Advanced Intrusion Detection Environment) monitor file changes:
    sudo apt install aide
    sudo aideinit  # Initialize baseline
    sudo aide --check  # Compare current state to baseline

Backup and Recovery

  • Regularly back up critical data (e.g., /etc, /home, databases).
  • Test backups to ensure they can be restored.

Code Examples and Demos

Example 1: Securing a Sensitive Configuration File

# Create a sensitive config file
echo "db_password=secret" > /etc/app/config.conf

# Restrict permissions to root-only read
sudo chown root:root /etc/app/config.conf
sudo chmod 400 /etc/app/config.conf

# Verify
ls -l /etc/app/config.conf
-r-------- 1 root root 19 Jun 1 14:00 /etc/app/config.conf

Example 2: Creating a Restricted User for a Service

# Create a system user with no login shell
sudo useradd -r -s /usr/sbin/nologin appuser

# Run a service as appuser (systemd example)
# /etc/systemd/system/myapp.service
[Service]
User=appuser
ExecStart=/usr/bin/myapp

Example 3: Granting Capabilities to a Web Server

# Nginx normally needs CAP_NET_BIND_SERVICE for port 80
sudo setcap 'cap_net_bind_service=+ep' /usr/sbin/nginx

# Start Nginx as non-root (edit /etc/nginx/nginx.conf: user nginx;)
sudo systemctl restart nginx

Example 4: AppArmor Profile for a Python Script

# Profile: /etc/apparmor.d/usr.local.bin.my_script
/usr/local/bin/my_script {
  # Allow Python libraries
  /usr/lib/python3.*/** r,
  # Allow read access to input files
  /srv/data/*.txt r,
  # Deny network access
  network deny,
}

# Enforce the profile
sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.my_script

Conclusion

The Linux security model is a powerful, layered framework that balances flexibility with protection. By mastering DAC (permissions, users, capabilities) and MAC (SELinux/AppArmor), you can enforce least privilege, minimize attack surfaces, and defend against modern threats. Remember: security is an ongoing process—regular updates, audits, and adherence to best practices are critical. Whether securing a personal laptop or a production server, the principles outlined here will help you build resilient Linux systems.

References