Trouver les images vulnérables à la faille log4j avec bash et trivy dans k8s

Sommaire

Il y a quelques jours, le 10 décembre 2021, une vulnérabilité critique a été découverte sur Apache Log4j 2, une librairie Java pour la gestion des logs. Cette faille permettant l'exécution de code à distance est surnommée Log4Shell.

C'est une bonne opportunité pour jouer avec bash, pour trouver au sein de cluster Kubernetes quelles images de pods sont impactés.

Lister les images du cluster

Lister les pods est assez facile, mais lister les images est un tout petit peu plus compliqué. Nous devons jouer avec l'option jsonpath pour sélectionner l'image.

La commande suivante permet de lister toutes les images de pods s'exécutant dans un namespace:

1$ kubectl get pods -o jsonpath={range .items[*]}{.spec.containers[*].image}{“ “}

Ajoutons à cela quelque lignes magiques de bash pour classer, avoir les images des sidecars et dédupliquer la sortie, cela donne le résultat suivant :

 1$ kubectl get pods -o jsonpath='{range .items[*]}{.spec.containers[*].image}{" "}' | tr " " "\n" | sort -u
 2consul:1.3.0
 3elasticsearch:5.6.13
 4grafana/grafana:5.1.0
 5jboss/keycloak:4.5.0.Final
 6jhipster/consul-config-loader:v0.3.0
 7jhipster/jhipster-console:v4.0.0
 8jhipster/jhipster-elasticsearch:v4.0.0
 9jhipster/jhipster-logstash:v4.0.0
10jhipster/jhipster-zipkin:v4.0.0
11mariadb:10.5
12mongo:4.0.2
13nextcloud:20.0.6-apache
14postgres:10.4

Maintenant que nous pouvons récupérer les images, utilisons trivy.

Trivy

Trivy est un scanner de sécurité open source développé par la société Aquasecurity. Il scanne vos images, pour y trouver toutes les vulnérabilités "CVE". Ce logiciel est embarqué dans d'autres outils "DevSecOps", comme VMware Harbor, GitLab, et d'autres.

Pour l'installer sur votre OS favori, cela se passe par la : https://aquasecurity.github.io/trivy/v0.21.2/getting-started/installation/.

L'utilisation de trivy est très simple. Par exemple, pour voir les vulnérabilités d'une image lancez la commande suivante :

1$ trivy image — severity CRITICAL elasticsearch:5.6.13

Le résultat parle de lui-même:

 1$ trivy image --severity CRITICAL elasticsearch:5.6.13
 22021-12-12T21:20:06.322+0100    INFO    Detected OS: debian
 32021-12-12T21:20:06.322+0100    INFO    Detecting Debian vulnerabilities...
 42021-12-12T21:20:06.350+0100    INFO    Number of language-specific files: 1
 52021-12-12T21:20:06.350+0100    INFO    Detecting jar vulnerabilities...
 6
 7Java (jar)
 8==========
 9Total: 6 (CRITICAL: 6)
10
11+-------------------------------------+------------------+----------+-------------------+---------------+---------------------------------------+
12|               LIBRARY               | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |                 TITLE                 |
13+-------------------------------------+------------------+----------+-------------------+---------------+---------------------------------------+
14| io.netty:netty                      | CVE-2019-20444   | CRITICAL | 3.10.6.Final      | 4.1.44.Final  | netty: HTTP request smuggling         |
15|                                     |                  |          |                   |               | -->avd.aquasec.com/nvd/cve-2019-20444 |
16+                                     +------------------+          +                   +               +---------------------------------------+
17|                                     | CVE-2019-20445   |          |                   |               | netty: HttpObjectDecoder.java allows  |
18|                                     |                  |          |                   |               | Content-Length header to accompanied  |
19|                                     |                  |          |                   |               | by second Content-Length header       |
20|                                     |                  |          |                   |               | -->avd.aquasec.com/nvd/cve-2019-20445 |
21+-------------------------------------+------------------+          +-------------------+---------------+---------------------------------------+
22| io.netty:netty-handler              | CVE-2019-20444   |          | 4.1.13.Final      | 4.1.44        | netty: HTTP request smuggling         |
23|                                     |                  |          |                   |               | -->avd.aquasec.com/nvd/cve-2019-20444 |
24+                                     +------------------+          +                   +---------------+---------------------------------------+
25|                                     | CVE-2019-20445   |          |                   | 4.1.45        | netty: HttpObjectDecoder.java allows  |
26|                                     |                  |          |                   |               | Content-Length header to accompanied  |
27|                                     |                  |          |                   |               | by second Content-Length header       |
28|                                     |                  |          |                   |               | -->avd.aquasec.com/nvd/cve-2019-20445 |
29+-------------------------------------+------------------+          +-------------------+---------------+---------------------------------------+
30| org.apache.logging.log4j:log4j-api  | CVE-2021-44228   |          | 2.11.1            | 2.15.0        | log4j-core: Remote code execution     |
31|                                     |                  |          |                   |               | in Log4j 2.x when logs contain        |
32|                                     |                  |          |                   |               | an attacker-controlled...             |
33|                                     |                  |          |                   |               | -->avd.aquasec.com/nvd/cve-2021-44228 |
34+-------------------------------------+                  +          +                   +               +                                       +
35| org.apache.logging.log4j:log4j-core |                  |          |                   |               |                                       |
36|                                     |                  |          |                   |               |                                       |
37|                                     |                  |          |                   |               |                                       |
38|                                     |                  |          |                   |               |                                       |
39+-------------------------------------+------------------+----------+-------------------+---------------+---------------------------------------+

On voit que la vulnérabilité CVE-2021–44228 est présente, nous devons patcher ou mettre à jour dès que possible !

Bash & Trivy

Edit (15/12/2021) : Il existe un plug-in tout fait pour cela ! Voir ici: https://github.com/aquasecurity/trivy-plugin-kubectl

Ok, maintenant que nous avons la liste des images dans notre cluster, que nous savons scanner une image, allons plus loin, et bouclons !

Voici un script bash permettant cela juste ci-dessous. Amusez-vous avec ! Notez que dans l'exemple nous listons les images du namespace courant. Vous pouvez l'améliorer au besoin.

 1#!/usr/bin/env bash
 2RED='\033[0;31m'
 3NC='\033[0m'
 4
 5OLDIFS="$IFS"
 6IFS=$'\n'
 7VULN=$1
 8
 9# $1 arg is the CVE number to check
10if [ -z $1 ]; then
11  echo -e "usage: $0 CVE-NUMBER (i.e: './k8s_vuln.sh CVE-2021-44228')"
12  exit
13fi
14
15# Check command existence before using it
16if ! command -v trivy &> /dev/null; then
17  echo "trivy not found, please install it"
18  exit
19fi
20if ! command -v kubectl &> /dev/null; then
21  echo "kubectl not found, please install it"
22  exit
23fi
24
25# CVE-2021-44228
26echo "Scanning $1..."
27
28namespaces=`kubectl get ns | cut -d' ' -f 1 | tail -n+2`
29for ns in ${namespaces}; do
30  echo "- scanning in namespace ${ns}"
31  imgs=`kubectl get pods,deployments,daemonsets,statefulsets,jobs,cronjobs -n ${ns} -o jsonpath='{range .items[*]}{.spec.containers[*].image}{" "}' | tr " " "\n" | sort -u`
32  for img in ${imgs}; do
33    echo "  scanning ${img}"
34    result=`trivy -q image --light --no-progress --severity CRITICAL ${img}`
35    if echo ${result} | grep -q "$1" ; then
36      echo -e "  ${RED}${img} is vulnerable, please patch!${NC}"
37    fi
38  done
39done
40
41IFS="$OLDIFS"

Bash script k8s vulnerability

Etapes suivantes

Ceci était un rapide exemple d'utilisation bash, mais vous pouvez utiliser des outils de sécurité plus avancé pour être alerté de telles failles, comme Sysdig Secure, Snyk ou d'autres !

References