forked from quentin/quentin.dufour.io
119 lines
6 KiB
Markdown
119 lines
6 KiB
Markdown
---
|
|
layout: post
|
|
slug: hardening-lxc-containers-running-systemd
|
|
status: draft
|
|
sitemap: true
|
|
title: Hardening LXC containers running systemd
|
|
description: An epic trying to drop CAP\_SYS\_ADMIN
|
|
disqus: false
|
|
categories:
|
|
tags:
|
|
- security
|
|
- linux
|
|
- containers
|
|
---
|
|
|
|
![A real container](/assets/images/posts/harden-container.jpg)
|
|
<div style="font-size: 12px; text-align:center; margin-top:-20px">
|
|
*A container. Photo by [Mr. Rollers](https://www.flickr.com/photos/mr-rollers/32972266123/). CC BY-NC-ND 2.0*
|
|
</div>
|
|
|
|
Hardening Linux Containers, and more especially [LXC containers](https://linuxcontainers.org/fr/lxc/introduction/), is needed to prevent a malicious user to escape your container. But before starting, we need to understand how containers work under the hood.
|
|
|
|
As said by Jessie Frazelle in her blog post [Setting the Record Straight: containers vs. Zones vs. Jails vs. VMs](https://blog.jessfraz.com/post/containers-zones-jails-vms/), containers in Linux are not a top level design like Zone in Solaris and Jails in BSD.
|
|
|
|
> A "container" is just a term people use to describe a combination of Linux namespaces and cgroups. Linux namespaces and cgroups ARE first class objects. NOT containers.
|
|
|
|
In this article, we'll discuss the different "primitives" exposed by the Linux kernel like *namespaces*, *cgroups*, *Linux Security Modules*, *capabilities* and *seccomp*. Our container tool like LXC or Docker, which is a user space binary, will interact with these primitives. We'll see that we can interact with them through the LXC configuration file to improve (or worsen) the security of our LXC container.
|
|
|
|
The challenge when it comes to hardening a LXC container, compared to other solutions, is that there is a great probability that you'll run systemd in your container. And systemd heavily uses the primitives quoted before. Especially, systemd rely on *cgroups* to handle its services. We can also mention that many systemd daemon will be provided with a configuration that need to interact with the *capabilities*.
|
|
|
|
If you feel a bit lost with all these terms, a good start is the reading of this whitepaper by the NCCGroup: [Understanding and Hardening Linux Containers](https://www.nccgroup.trust/us/our-research/understanding-and-hardening-linux-containers/). This post is also inspired by the article written by Christian Seiler, [LXC containers without CAP\_SYS\_ADMIN under Debian Jessie](https://blog.iwakd.de/lxc-cap_sys_admin-jessie), but we'll see that, due to evolutions in the Linux kernel, the proposed configuration does not work anymore out of the box.
|
|
|
|
## Creating a standard LXC container
|
|
|
|
![A factory](/assets/images/posts/harden-factory.jpg)
|
|
<div style="font-size: 12px; text-align:center; margin-top:-20px">
|
|
*A factory building containers ? Photo by [Thomas Berg](https://www.flickr.com/photos/decafinata/1989725289/). CC BY-SA 2.0*
|
|
</div>
|
|
|
|
Before starting, you'll need a very recent version of LXC, at least lxc-2.0.9 (not yet released as of this writing). Fortunately, you can compile it from its master branch. We'll see later why we need a such recent version.
|
|
Here is a quick reminder on how to compile LXC:
|
|
|
|
```bash
|
|
git clone https://github.com/lxc/lxc
|
|
cd lxc
|
|
./autogen.sh
|
|
./configure
|
|
make -j8
|
|
sudo make install
|
|
```
|
|
|
|
Now let's create a basic container (we'll use Fedora but the instructions should work for every distributions):
|
|
|
|
```bash
|
|
sudo lxc-create -n harden -t fedora
|
|
```
|
|
|
|
As you'll need to debug the launch of your container, I can only recommend you this command line :
|
|
|
|
```bash
|
|
sudo lxc-start -n harden -lDEBUG -F
|
|
```
|
|
|
|
It will launch your container in foreground (so you'll be able to see systemd logs at boot) and it will log many useful informations in the `/var/log/lxc/harden.log` file.
|
|
|
|
## Capabilities: split the root
|
|
|
|
![Puzzle](/assets/images/posts/harden-puzzle.jpg)
|
|
<div style="font-size: 12px; text-align:center; margin-top:-20px">
|
|
*The great puzzle of root. Photo by [Kevin Dooley](https://www.flickr.com/photos/pagedooley/14555354976). CC BY 2.0.*
|
|
</div>
|
|
|
|
## cgroups: group your processes
|
|
|
|
![Lions](/assets/images/posts/harden-lions.jpg)
|
|
<div style="font-size: 12px; text-align:center; margin-top:-20px">
|
|
*A cgroup of lions with parents and children. Photo by [Joel Herzog](https://unsplash.com/@joel_herzog). Unsplash license.*
|
|
</div>
|
|
|
|
[Wikipedia](https://en.wikipedia.org/wiki/Cgroups) proposes the following definition:
|
|
|
|
> cgroups is a Linux kernel feature that limits, accounts for, and isolates the resource usage (CPU, memory, disk I/O, network, etc.) of a collection of processes.
|
|
|
|
It might not be totally clear at the first read, but cgroups are two differents things:
|
|
|
|
1. A method to create groups of processus
|
|
2. A method to apply limitation, accounting, etc. on these groups
|
|
|
|
<span></span>
|
|
|
|
If you want to read more on this, the article [Control Groups vs. Control Groups](http://0pointer.de/blog/projects/cgroups-vs-cgroups.html) by Lennart Poettering explains how systemd uses cgroups and why the distinction is crucial.
|
|
|
|
## Namespaces: isolate your system resources
|
|
|
|
Michael Kerrisk wrote an interesting [serie of articles about namespaces](https://lwn.net/Articles/531114/) on LWN. I find its definition of namespaces particularly interesting:
|
|
|
|
> The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource.
|
|
|
|
At first glance, namespaces handle could appear trivial in LXC: every available namespaces are used and that's all.
|
|
|
|
## Seccomp: filter your syscalls
|
|
|
|
![Barriers](/assets/images/posts/harden-barrier.jpg)
|
|
<div style="font-size: 12px; text-align:center; margin-top:-20px">
|
|
*The seccomp barrier protects the access to the kernel. Photo by [Mike Wilson](https://unsplash.com/@mkwlsn). Unsplash license.*
|
|
</div>
|
|
|
|
## LSM: mandatory access control
|
|
|
|
![Top Secret](/assets/images/posts/harden-secret.jpg)
|
|
<div style="font-size: 12px; text-align:center; margin-top:-20px">
|
|
*Back to the origin. Photo by [Michelangelo Carrieri](https://www.flickr.com/photos/malakhkelevra/4951863053). CC BY-ND 2.0*
|
|
</div>
|
|
|
|
## Other
|
|
|
|
### prlimit
|
|
|
|
### /dev
|