Scanning vulnerable Docker images

Mihir Shah
4 min readJul 21, 2019

Talking about red teaming and scanning images for vulnerabilities inside a containerized environment is a very tedious task at hand. Lets first talk and understand what would we do conventionally? Well, I for one would first start scanning each application running as a service inside the container. I would then start looking for vulnerabilities pertaining to each application manually, and then document it and try attacking the vulns. That being said, I would leave the job at hand and would give up midway. The solution to this nuance is using Clair which is an API driven tool from CoreOS.

When it comes to containerization technologies, docker has become the De-Facto to run and deploy applications On-The-Go. With all the benefits that are shipped along with the installation of Docker on a system, developers find it easy to simply run an application inside a container. Docker, by itself, is very secured and runs inside a sandbox — meaning Isolated from other processes/applications. But the application running within the container might be vulnerable which has its CVE; waiting to be discovered. In this article, we would be looking at installing Clair (Our way), creating our lab, Finding CVEs in certain docker images and then a follow up to the sandbox escape.

Installing Clair

If you are keen on following the conventional method of installing Clair to your environment, then take it from me, you would have traveled to the moon and back but would be still troubleshooting some error on stack overflow. I came up with this method to set up your own lab environment for scanning images locally. Note: For this to work- you need to have docker-compose installed on your Docker engine. The way I have designed the working of this is — There would be three docker containers running on the system.

  1. The first container would be running your Testing Image which would be from your private registry
  2. The second container would be running Clair within CoreOS inside a container which will be responsible for actual scanning of the images
  3. The Third container would be a PostgreSQL docker image, which will be storing all the CVEs (This has to be updated manually as of now).

To create an environment for this, clone/download the configuration.yaml files from my GitHub from here. The configuration files automate the creation of a private network and all the containers are added to the network, this makes the communication amongst the container a tad bit easier rather than creating individual links amongst them all.

The way the setup works is:

  • After pulling the image you wish to scan, tag the image to any desired name and then push it to your private registry locally.
  • Use Clair to scan the images against the CVEs listed in the PostgreSQL database
  • If any vulnerability matches and the CVE is found, it is copied and stored to persistent volume storage.

Running Clair

After cloning the repo, cd into the directory and execute —

docker-compose up -d

this would create the environment required to run the images. after all the container are up and running (check it using docker ps) install klar.

Klar is a CLI tool which helps in interacting with Clair. Clair is, after all, an API driven application which pertains to scanning and reporting of vulnerabilities. The installation procedure for klar could be found here.

Once everything is up and running let’s get our hands-on. In this demo, we will first pull the latest version of the Nginx image from the docker hub and then tag it, so that we can use our image for testing purposes and later push it to our local registry and confine to our newly created container for the same.

docker pull nginx:latest
docker tag nginx localhost:5000/nginx-test
docker push localhost:5000/nginx-test

These commands would do the needful. Now the only thing left to do is to run Clair and find vulnerabilities on our image. To interact with Clair through our CLI helper klar, execute the following command —

CLAIR_ADDR=http://localhost:6060 CLAIR_OUTPUT=Low CLAIR_THRESHOLD=10 REGISTRY_INSECURE=TRUE klar localhost:5000/nginx-test

This basically creates local variables — ‘CLAIR_ADDR’, which holds the URI to run Clair as a String; ‘CLAIR_OUTPUT’ This informs Clair to output all the CVEs found with vulnerabilities — Low, Medium, High and Critical. ‘CLAIR_THRESHOLD=10 REGISTRY_INSECURE=TRUE’ — this is a mandate variable to be declared for running Clair, All these variables are then accessed by klar before passing them as arguments for running Clair. The output after running Clair on Nginx looks like this

setting up the environment
After running Clair on the latest Nginx image — at the time of this writing

In the upcoming posts, I’ll be blogging about different techniques to attack a docker container and to escape the sandboxed protection by leveraging multiple CVEs on docker engine and by misconfigurations. Stay tuned for more interesting blogs, Also any pulls for improving the environment would be appreciated. Feel free to comment below.



Mihir Shah

Author | Patent holder on cloud security | Industry mentor @Stanford University.