Auditar vulnerabilidades en imágenes Docker

Intro

Los microservicios ofrecidos desde la plataforma Docker también se encuentran expuestas a vulnerabilidades que pueden ser explotadas como si de un servidor se tratara. A fin de cuentas, se trata de un sistema operativo con una conectividad propia o compartida y con la posibilidad de tener algún puerto expuesto por el que poder acceder.

No es mala práctica mantener nuestras imágenes auditadas, a partir de las cuales levantaremos los Contenedores. Para ello usaremos una sencilla herramienta llamada Trivy, que puede ser instalada en el sistema o a partir de su propio contenedor de Docker. En esta entrada usaremos la segunda opción, ya que al utilizar el contenedor no será necesario realizar instalación alguna, siendo mucho más cómoda su explicación.

Esta herramienta no soporta arquitectura ARM, por lo que no se podrá utilizar desde un dispositivo como RapsberryPi.


Entorno de prueba

Vamos a utilizar un servidor Debian en el que tendremos instalador el software Docker.
También usaremos la imagen oficial de Ubuntu, la cual instalaremos con el siguiente comando:

$ docker pull ubuntu:latest

La imagen quedaría descargada:

$ docker images

REPOSITORY                 TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              1d622ef86b13        7 weeks ago         73.9MB

Antes de realizar el análisis, vamos a crear un directorio caché en el que descargar toda la información que el programa utilizará durante el escaneo, y el cual indicaremos en cada comando a ejecutar:

mkdir /root/Trivy-Docker

Análisis

Vamos a realizar un análisis usando el servicio Docker de nuestro host anfitrión para realizar el escáner de vulnerabilidades.

Imagen recién descargada

Analizaremos la imagen recién descargada ubuntu:latest:

$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v /root/Trivy-Docker/:/root/.cache/ aquasec/trivy ubuntu:latest

2020-06-16T19:51:03.846Z        WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-06-16T19:51:03.849Z        INFO    Need to update DB
2020-06-16T19:51:03.849Z        INFO    Downloading DB...
50.58 KiB / 16.60 MiB [>_____________________________________________________________] 0.30% ? p/s ?288.58 KiB / 16.60 MiB [->___________________________________________________________] 1.                                                70% ? p/s ?1.18 MiB / 16.60 MiB [---->__________________________________________________________] 7.10% ? p/s ?3.09 MiB / 16.60 MiB [--------->________________________________________] 18.6                                                4% 5.07 MiB p/s ETA 2s5.91 MiB / 16.60 MiB [----------------->________________________________] 35.60% 5.07 MiB p/s ETA 2s9.87 MiB / 16.60 MiB [----------------------------->_______________                                                _____] 59.44% 5.07 MiB p/s ETA 1s13.96 MiB / 16.60 MiB [----------------------------------------->_______] 84.11% 5.91 MiB p/s ETA 0s16.60 MiB / 16.60 MiB [---------------------------------                                                ------------------] 100.00% 12.43 MiB p/s 2s2020-06-16T19:51:09.567Z    INFO    Detecting Ubuntu vulnerabilities...

ubuntu:latest (ubuntu 20.04)
============================
Total: 26 (UNKNOWN: 0, LOW: 18, MEDIUM: 7, HIGH: 1, CRITICAL: 0)

+---------------+------------------+----------+-------------------+-------------------+--------------------------------+
|    LIBRARY    | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |   FIXED VERSION   |             TITLE              |
+---------------+------------------+----------+-------------------+-------------------+--------------------------------+
| apt           | CVE-2020-3810    | MEDIUM   | 2.0.2             | 2.0.2ubuntu0.1    | Missing input validation in    |
|               |                  |          |                   |                   | the ar/tar implementations of  |
|               |                  |          |                   |                   | APT before version 2.1.2...    |
+---------------+------------------+----------+-------------------+-------------------+--------------------------------+
| bash          | CVE-2019-18276   | LOW      | 5.0-6ubuntu1      |                   | bash: when effective UID is    |
|               |                  |          |                   |                   | not equal to its real UID      |
|               |                  |          |                   |                   | the...                         |
+---------------+------------------+          +-------------------+-------------------+--------------------------------+
| coreutils     | CVE-2016-2781    |          | 8.30-3ubuntu2     |                   | coreutils: Non-privileged      |
|               |                  |          |                   |                   | session can escape to the      |
|               |                  |          |                   |                   | parent session in chroot       |
+---------------+------------------+          +-------------------+-------------------+--------------------------------+
| dpkg          | CVE-2017-8283    |          | 1.19.7ubuntu3     |                   | dpkg-source in dpkg 1.3.0      |
|               |                  |          |                   |                   | through 1.18.23 is able to use |
|               |                  |          |                   |                   | a non-GNU...                   |
+---------------+------------------+          +-------------------+-------------------+--------------------------------+
...

Acortamos el resultado ya que es muy largo. Vemos que se han identificado 26 vulnerabilidades, distribuidas en criticidad Low, Medium y High. Esto quiere decir, que si levantamos un Contenedor a partir de esta imagen y no lo actualizamos tendrá vulnerabilidades desde el primer momento.

Imagen actualizada

Para evitar tener la imagen en este estado vamos a levantar un Contenedor a partir de esta, lo actualizaremos y crearemos una imagen a partir de este, la cual auditaremos en busca de vulnerabilidades.

Levantamos el contenedor:

$ docker container run -itd ubuntu:latest

56c87dfe8a46976d8e1fdf0a4ec83f9589973e620c121fc9262969d553747b52
root@h2847530:~# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
56c87dfe8a46        ubuntu:latest       "/bin/bash"         3 seconds ago       Up 1 second                             vibrant_allen

Accedemos a este, lo actualizamos y salimos:

$ docker container exec -it 56c87dfe8a46 bash

root@56c87dfe8a46:/$
root@56c87dfe8a46:/$apt update
...
root@56c87dfe8a46:/$apt-get dist-upgrade
...
root@56c87dfe8a46:/$exit

Creamos una imagen a partir de este contenedor actualizado, la cual llamaremos ubuntu-updated:

docker commit 56c87dfe8a46 ubuntu-updated

La imagen estaría creada:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu-updated      latest              e37a75457fe4        24 hours ago        103MB
ubuntu              latest              1d622ef86b13        7 weeks ago         73.9MB

Escaneamos la nueva imagen en busca de vulnerabilidades:

$ docker run --rm  -v /var/run/docker.sock:/var/run/docker.sock   -v /root/Trivy-Docker/:/root/.cache/ aquasec/trivy  ubuntu-updated

2020-06-16T20:02:45.595Z        WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-06-16T20:02:47.520Z        INFO    Detecting Ubuntu vulnerabilities...

ubuntu-updated (ubuntu 20.04)
=============================
Total: 23 (UNKNOWN: 0, LOW: 18, MEDIUM: 5, HIGH: 0, CRITICAL: 0)

+-------------+------------------+----------+-------------------+---------------+--------------------------------+
|   LIBRARY   | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |             TITLE              |
+-------------+------------------+----------+-------------------+---------------+--------------------------------+
| bash        | CVE-2019-18276   | LOW      | 5.0-6ubuntu1      |               | bash: when effective UID is    |
|             |                  |          |                   |               | not equal to its real UID      |
|             |                  |          |                   |               | the...                         |
+-------------+------------------+          +-------------------+---------------+--------------------------------+
| coreutils   | CVE-2016-2781    |          | 8.30-3ubuntu2     |               | coreutils: Non-privileged      |
|             |                  |          |                   |               | session can escape to the      |
|             |                  |          |                   |               | parent session in chroot       |
+-------------+------------------+          +-------------------+---------------+--------------------------------+
| dpkg        | CVE-2017-8283    |          | 1.19.7ubuntu3     |               | dpkg-source in dpkg 1.3.0      |
|             |                  |          |                   |               | through 1.18.23 is able to use |
|             |                  |          |                   |               | a non-GNU...                   |
+-------------+------------------+          +-------------------+---------------+--------------------------------+
| gpgv        | CVE-2019-13050   |          | 2.2.19-3ubuntu2   |               | GnuPG: interaction between the |
|             |                  |          |                   |               | sks-keyserver code and GnuPG   |
|             |                  |          |                   |               | allows for a Certificate...    |
+-------------+------------------+          +-------------------+---------------+--------------------------------+
...

Recortamos el resultado final, ya que es muylargo. Vemos que se han localizado 23 vulnerabilidades, distribuidas en criticidad Low, Medium y High. Esto quiere decir, se han solucionado algunas vulnerabilidades con la actualización del Contenedor.


Interpretar el resultado

Como hemos visto, se muestran demasiados resultados, muchos de ellos son motivados por:

  • Vulnerabilidades muy antiguas y que no han sido solucionadas, posiblemente por no suponer un problema serio de seguridad.
  • Problemas de seguridad reportados pero que aún no tienen un candidato en el que se soluciona.

En ambos casos, si analizamos los resultados obtenidos observamos que la columna Fixed version se encuentra vacía en la imagen actualizada ubuntu-updated, indicando que no hay candidato para solucionar la vulnerabilidad. Por lo tanto, es en los casos en los que aparece una versión más actual en los que debemos poner la mayor atención.

Para interpretar los datos que realmente podamos solucionar tenemos una opción a utilizar al ejecutar el escáner, la cual veremos en la siguiente sección.


Opciones del programa

Para obtener una información más reducida, fácil de interpretar y manejar, podemos usar las siguientes opciones:

  • light: con esta opción eliminamos los detalles de cada vulnerabilidad:
$ docker run --rm  -v /var/run/docker.sock:/var/run/docker.sock -v /root/Trivy-Docker/:/root/.cache/ aquasec/trivy  --light  ubuntu-updated

2020-06-16T21:34:52.737Z        WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
2020-06-16T21:34:52.739Z        INFO    Need to update DB
2020-06-16T21:34:52.739Z        INFO    Downloading DB...
50.57 KiB / 4.40 MiB [>______________________________________________________________] 1.12% ? p/s ?254.57 KiB / 4.40 MiB [--->__________________________________________________________] 5.65% ? p/s ?866.57 KiB / 4.40 MiB [----------->_________________________________________________] 19.24% ? p/s ?2.19 MiB / 4.40 MiB [------------------------->_________________________] 49.84% 3.57 MiB p/s ETA 0s4.40 MiB / 4.40 MiB [------------------------------------------------->] 100.00% 3.57 MiB p/s ETA 0s4.40 MiB / 4.40 MiB [------------------------------------------------------] 100.00% 4.79 MiB p/s 1s2020-06-16T21:34:55.044Z  INFO    Detecting Ubuntu vulnerabilities...

ubuntu-updated (ubuntu 20.04)
=============================
Total: 23 (UNKNOWN: 0, LOW: 18, MEDIUM: 5, HIGH: 0, CRITICAL: 0)

+-------------+------------------+----------+-------------------+---------------+
|   LIBRARY   | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |
+-------------+------------------+----------+-------------------+---------------+
| bash        | CVE-2019-18276   | LOW      | 5.0-6ubuntu1      |               |
+-------------+------------------+          +-------------------+---------------+
| coreutils   | CVE-2016-2781    |          | 8.30-3ubuntu2     |               |
+-------------+------------------+          +-------------------+---------------+
| dpkg        | CVE-2017-8283    |          | 1.19.7ubuntu3     |               |
+-------------+------------------+          +-------------------+---------------+
| gpgv        | CVE-2019-13050   |          | 2.2.19-3ubuntu2   |               |
+-------------+------------------+          +-------------------+---------------+
| libc-bin    | CVE-2016-10228   |          | 2.31-0ubuntu9     |               |
+             +------------------+          +                   +---------------+
|             | CVE-2020-6096    |          |                   |               |
...
  • ignore-fixed: con esta opción no se mostrarían las vulnerabilidades sin una versión que la solucione. Por ejemplo:

Nuestra imagen de ubuntu:latest descargada, con varias vulnerabilidades detectadas:

$ docker run --rm  -v /var/run/docker.sock:/var/run/docker.sock   -v /root/Trivy-Docker/:/root/.cache/ aquasec/trivy  --light --ignore-unfixed ubuntu:latest

	2020-06-16T21:56:55.948Z        WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
	2020-06-16T21:56:55.966Z        INFO    Detecting Ubuntu vulnerabilities...
	
	ubuntu (ubuntu 20.04)
	=====================
	Total: 3 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 1, CRITICAL: 0)
	
	+---------------+------------------+----------+-------------------+-------------------+
	|    LIBRARY    | VULNERABILITY ID | SEVERITY | INSTALLED VERSION |   FIXED VERSION   |
	+---------------+------------------+----------+-------------------+-------------------+
	| apt           | CVE-2020-3810    | MEDIUM   | 2.0.2             | 2.0.2ubuntu0.1    |
	+---------------+                  +          +                   +                   +
	| libapt-pkg6.0 |                  |          |                   |                   |
	+---------------+------------------+----------+-------------------+-------------------+
	| libgnutls30   | CVE-2020-13777   | HIGH     | 3.6.13-2ubuntu1   | 3.6.13-2ubuntu1.1 |
	+---------------+------------------+----------+-------------------+-------------------+

Nuestra imagen ubuntu-updated actualizada, y sin vulnerabilidades pendiente de aplicar:

$ docker run --rm  -v /var/run/docker.sock:/var/run/docker.sock   -v /root/Trivy-Docker/:/root/.cache/ aquasec/trivy  --light --ignore-unfixed ubuntu-updated

	2020-06-16T21:58:19.088Z        WARN    You should avoid using the :latest tag as it is cached. You need to specify '--clear-cache' option when :latest image is changed
	2020-06-16T21:58:19.110Z        INFO    Detecting Ubuntu vulnerabilities...
	
	ubuntu-updated (ubuntu 20.04)
	=============================
	Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

Conclusión

Como hemos visto, actualizar nuestros Contenedores es una tarea que debería de estar incluida en cualquier programaicón de tareas de seguridad, como si de un servidor convencional se tratara, sobre todo si exponemos alguno de sus puertos a través del Docker Host en alguna de sus interfaces públicas.


Herramientas similares

Otras herramientas similares, pero más complejas de utilizar, serían:

  • Anchore Engine, con una versión en Docker disponible: https://github.com/anchore/anchore-engine
  • Claire + Klar, desplegadas en tecnologías Docker: https://github.com/quay/clair y https://github.com/optiopay/klar

Enlaces de interés

Página oficial del proyecto Trivy.