24.10.2024

Docker user: how to work with users?

Different solutions can be used to work with virtualised environments, but the most popular is still Docker. Its work is based on isolation of environments that are attached to a single PID, creating an environment for running software. As a result, this guest environment appears on the host OS as a set of processes that are further restricted via Cgroups.

Therefore, the work with users on containers and the host machine also happens through the kernel, or rather their authorisation.

Recall that when the utility is running, it authenticates the user via PAM, checks his authenticity, and then assigns rights to the process.

So, in an isolated environment, file-based authentication is easy because /etc/shadow is at the owner's disposal. And there is no further authentication at the kernel level, only rights differentiation! Consequently, you need to secure your host OS from escaping from the container of intruders who could get in via the conditional web!

How does Docker manage users?

To reveal the algorithm of working with users in virtual environments, let's consider the scheme. Initially, the developers foresaw a potential problem with illegitimate access in environments that share a common core. Therefore, they solved the problem by adding user mapping to the tools.

Screenshot №1 — Schema

Let's consider two scenarios according to the scheme: the first one without User mapper and the second one with it. Since a separate environment with an isolated file system is created in the container, the user IDs of the guest environment and the host environment may coincide. This means that a fake root in the guest environment has the same root privileges in the host environment. These possibilities will cause damage to the system, provided that the host volumes are connected.

An attack from the container when deploying a user

Let's consider the classic creation of a user in a container. To do this, let's go to the machine and pre-install Docker:

sudo apt install docker.io docker-compose -y && systemctl start docker && \
systemctl status docker 

Screenshot №2 — Initial step

Let's make sure the service is running and write two files: Dockerfile and Docker-compose.

FROM ubuntu:latest

RUN apt-get update && apt-get install -y sudo

RUN groupadd -g 10000 usergroup && \
useradd -u 10000 -g usergroup -m -s /bin/bash user1 && \
echo "user1 ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

USER user1
WORKDIR /home/user1
CMD ["/bin/bash"]

Screenshot №2 — Dockerfile

In this Dockerfile, we directly set the UID and GID we need for the user to be isolated in their environment. The doc ker-compose that will allow us to create the container is as follows:

version: '3'
services:
ubuntu:
build:
context: .
dockerfile: Dockerfile
container_name: ubuntu_container
tty: true
volumes:
- /tmp:/home/user/tmp

Screenshot №4 — Docker-compose

Let's run a build of this image with the container and then check to see if a user has actually been created:

sudo docker-compose up  && sudo docker exec -it ubuntu_container whoami

Screenshot №5 — Action in the container

Great, a user in the user1 container! But he had elevated permissions, either intentionally or not from the developer. And also attached the host directory in the work when deploying. Therefore, a file with elevated rights was created on behalf of root on the host:

Screenshot №6 — Compromised result

A basic solution is to limit fully mountable host volumes and use virtual ones instead, or to only allow host files to be readonly! Avoiding directories such as /etc/shadow.

volumes:
- /tmp:/home/user/tmp:ro

This way guest root can't harm the system, but if you still need to add system directories for whatever reason, that's where User Mapper comes into play.

How to map users from a container?

If you don't have sufficient resources than you can perform actions on powerful cloud servers. Serverspace provides isolated VPS / VDS servers for common and virtualize usage.

Screenshot №7 — Create Server

User Mapper changes the UID and GID before sending system calls. For example, to make root from the guest environment no longer have elevated privileges in the host environment, you just need to mapp the former to a user with lower privileges. To do this, open the configuration file /etc/docker/daemon.json and add:

{
"userns-remap": "dockremap"
}

This line says that all users in the guest environment will be represented on the host environment under the dockremap user. Let's create it and add it to the right group, where by default it will not have privileged rights:

sudo groupadd dockremap && \
sudo useradd -g dockremap dockremap

Screenshot №8 — Remap

And let's test the mapping by creating a new file in the shared directory on behalf of guest root:

Screenshot №9 — Result of remap

As a result, the newly created file has attributes not of root, but of the restricted user we set. But this method also has its disadvantages, the additional environment when mapping, slightly loads the work of the host OS. Therefore, this tool can be used only if you need to work with host data, in other cases you can do with the environment of the container or virtual volumes!