Archives Wild Code School
Docker

Docker - Analyse de vulnérabilité avec Trivy

Quête 2 sur 8 · 1 image archivée

La détection proactive des vulnérabilités est essentielle à la sécurité des conteneurs.

Cette quête se concentre sur Trivy, un outil open-source puissant qui permet d'analyser les images Docker pour identifier les failles de sécurité avant leur déploiement en production.


⚙️ Pré-requis

Avant de commencer cette quête, il est nécessaire de :

  • Savoir créer et exécuter des conteneurs Docker
  • Comprendre les concepts de base de la sécurité des conteneurs
  • Maîtriser les bonnes pratiques des Dockerfiles
  • Disposer d'un environnement Linux avec Docker installé

Et avoir réalisé au préalable les quêtes :


🎯 Objectifs :

✅ Comprendre les différents types de vulnérabilités dans les conteneurs ✅ Maîtriser l'utilisation de Trivy pour scanner les images Docker ✅ Interpréter et prioriser les résultats des analyses ✅ Mettre en place des stratégies de correction et de mitigation ✅ Intégrer les scans de sécurité dans un pipeline CI/CD

Les images Docker peuvent contenir différents types de vulnérabilités qui constituent des risques pour la sécurité des applications conteneurisées.

Comprendre ces vulnérabilités est essentiel pour les détecter et les corriger efficacement.

Types de vulnérabilités

1. Vulnérabilités des packages du système d'exploitation

Ces vulnérabilités affectent les packages du système d'exploitation de base utilisé dans l'image Docker (Debian, Alpine, Ubuntu, etc.).

Exemples courants :

  • Vulnérabilités dans OpenSSL pouvant conduire à des attaques cryptographiques
  • Failles dans des bibliothèques système comme glibc
  • Problèmes dans les utilitaires système comme bash ou sudo

Ces vulnérabilités sont particulièrement préoccupantes car elles affectent la fondation sur laquelle repose l'ensemble du conteneur.

2. Vulnérabilités des dépendances applicatives

Les applications conteneurisées dépendent souvent de nombreuses bibliothèques tierces, qui peuvent introduire des failles de sécurité.

Exemples :

  • Failles dans des frameworks web (Django, Flask, Express)
  • Vulnérabilités dans des bibliothèques de traitement comme pillow ou numpy
  • Faiblesses dans des bibliothèques de communication comme requests ou axios

Ces vulnérabilités sont particulièrement courantes car une application moderne peut facilement dépendre de centaines de packages, chacun pouvant introduire des risques.

3. Problèmes de configuration

Au-delà des vulnérabilités de code, les mauvaises configurations peuvent également exposer le conteneur à des risques.

Exemples :

  • Exécution en tant qu'utilisateur root
  • Utilisation de privilèges excessifs
  • Configurations de réseau ou de stockage dangereuses
  • Secrets exposés dans le Dockerfile ou l'image

Ces problèmes ne sont pas des "bugs" à proprement parler, mais des choix de configuration qui augmentent la surface d'attaque.

Base de données de vulnérabilités (CVE)

Les vulnérabilités de sécurité sont cataloguées dans des bases de données standardisées comme CVE (Common Vulnerabilities and Exposures), qui leur attribuent des identifiants uniques et documentent leur impact.

Chaque entrée CVE contient généralement :

  • Un identifiant unique (ex: CVE-2023-12345)
  • Une description de la vulnérabilité
  • Des informations sur les versions affectées
  • Une évaluation de la gravité (souvent selon le système CVSS)
  • Des références à des correctifs ou des mitigations

Les outils comme Trivy utilisent ces bases de données pour identifier les vulnérabilités connues dans les images Docker.

Comprendre le système CVSS

Le système CVSS (Common Vulnerability Scoring System) fournit une méthode standardisée pour évaluer la gravité des vulnérabilités de sécurité.

Les scores CVSS vont de 0 à 10, répartis en catégories :

  • Critique (9.0-10.0) : Impact total, exploitation facile et à distance
  • Élevé (7.0-8.9) : Compromission importante du système, exploitation relativement facile
  • Moyen (4.0-6.9) : Impact limité ou exploitation plus complexe
  • Faible (0.1-3.9) : Impact minimal ou exploitation très difficile

Le score CVSS prend en compte plusieurs facteurs :

  • Vecteur d'attaque (réseau, local, physique)
  • Complexité de l'attaque
  • Privilèges requis
  • Interaction de l'utilisateur nécessaire
  • Impact sur la confidentialité, l'intégrité et la disponibilité

Comprendre ces scores aide à prioriser les vulnérabilités à corriger en fonction de leur risque réel.

↗
https://nvd.nist.gov/vuln-metrics/cvss

National Vulnerability Database - CVSS

nvd.nist.gov
↗
https://www.cve.org/

CVE: Common Vulnerabilities and Exposures

cve.org

Trivy est un scanner de vulnérabilités open-source, conçu spécifiquement pour les conteneurs et les applications Cloud Native.

Développé par Aqua Security, cet outil est devenu un élément essentiel dans le pipeline CI/CD pour identifier les failles de sécurité dans les images Docker.

Principes de fonctionnement de Trivy

Trivy fonctionne en analysant le contenu d'une image Docker pour identifier les packages installés et leurs versions, puis en comparant ces informations avec des bases de données de vulnérabilités connues.

Le processus d'analyse comprend généralement les étapes suivantes :

  1. Extraction des métadonnées de l'image : Trivy examine chaque couche de l'image Docker pour identifier les packages installés.

  2. Détection des packages : L'outil identifie les gestionnaires de packages utilisés (apt, yum, pip, npm, etc.) et extrait la liste des packages installés avec leurs versions précises.

  3. Comparaison avec les bases de vulnérabilités : Ces informations sont comparées avec plusieurs bases de données de vulnérabilités, incluant les CVE et d'autres sources spécifiques à certains écosystèmes.

  4. Génération d'un rapport : Trivy produit un rapport détaillé des vulnérabilités trouvées, classées par niveau de gravité.

Installation de Trivy

Il existe plusieurs méthodes pour installer Trivy selon votre système d'exploitation.

bash
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
bash
sudo rpm -ivh https://github.com/aquasecurity/trivy/releases/download/v0.62.1/trivy_0.62.1_Linux-64bit.rpm
bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/.cache:/root/.cache aquasec/trivy:latest image alpine:3.21
Attention

Lorsqu'un numéro de version est précisée dans une ligne de commande, il faut bien penser à vérifier qu'il s'agit de la dernière version officielle à date !

La base de données Trivy

L'efficacité de Trivy repose sur sa base de données de vulnérabilités, qui est régulièrement mise à jour pour inclure les dernières failles découvertes.

Mise à jour de la base :

bash
trivy image --download-db-only

Cette commande télécharge la dernière version de la base de données sans effectuer d'analyse.

Emplacement de la base : La base de données est stockée par défaut dans : ~/.cache/trivy/

Sources utilisées : Trivy agrège des informations de plusieurs sources :

  • National Vulnerability Database (NVD)
  • Red Hat Security Data
  • Debian Security Bug Tracker
  • Ubuntu CVE Tracker
  • GitHub Advisory Database
  • Et d'autres sources spécifiques aux écosystèmes langages (PyPI, npm, RubyGems, etc.)

Cette approche multi-sources permet à Trivy d'offrir une couverture complète des vulnérabilités, y compris celles qui pourraient ne pas avoir encore reçu de CVE officiel.

↗
https://github.com/aquasecurity/trivy

GitHub - Trivy

github.com

Trivy offre de nombreuses fonctionnalités pour analyser les vulnérabilités des conteneurs Docker.

Voici comment l'utiliser efficacement dans différents scénarios.

Analyse d'une image Docker

La commande de base pour scanner une image Docker est :

bash
trivy image [options] IMAGE_NAME

Par exemple, pour analyser l'image nginx :

bash
trivy image nginx:1.25

Cette commande analyse l'image nginx:1.25 et affiche un rapport détaillé des vulnérabilités détectées, classées par niveau de gravité (CRITICAL, HIGH, MEDIUM, LOW).

Le résultat typique ressemble à ceci :

XXXX-YY-ZZT10:21:33.422Z        INFO    Detected OS: debian
XXXX-YY-ZZT10:21:33.422Z        INFO    Detecting Debian vulnerabilities...
XXXX-YY-ZZT10:21:33.559Z        INFO    Number of language-specific files: 0

nginx:1.25 (debian 12.4)
=========================
Total: 32 (CRITICAL: 2, HIGH: 8, MEDIUM: 15, LOW: 7, UNKNOWN: 0)

+----------------+------------------+----------+-------------------+---------------+---------------------------------------+
|    LIBRARY     | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION |                 TITLE                 |
+----------------+------------------+----------+-------------------+---------------+---------------------------------------+
| openssl        | CVE-2023-0464    | CRITICAL | 3.0.9-1           | 3.0.9-2       | OpenSSL: Possible DoS translating     |
|                |                  |          |                   |               | ASN.1 STRING types                    |
+----------------+------------------+----------+-------------------+---------------+---------------------------------------+
| libsystemd0    | CVE-2023-26604   | HIGH     | 252.6-1           | 252.6-2       | systemd: use-after-free in            |
|                |                  |          |                   |               | journald-server.c (moderate)          |
+----------------+------------------+----------+-------------------+---------------+---------------------------------------+
...

Options courantes de Trivy

Filtrer par sévérité

bash
trivy image --severity HIGH,CRITICAL nginx:1.25

Cette commande limite l'analyse aux vulnérabilités de niveau HIGH et CRITICAL uniquement, ce qui est particulièrement utile dans les pipelines CI/CD où l'on souhaite bloquer les déploiements uniquement si des problèmes graves sont détectés.

Formater la sortie

bash
# Format JSON
trivy image --format json --output results.json nginx:1.25

# Format pour intégration dans une table
trivy image --format table nginx:1.25

# Format pour intégration dans un pipeline CI/CD
trivy image --format template --template "@/path/to/template.tpl" nginx:1.25

Ces options permettent d'adapter la sortie de Trivy à différents cas d'utilisation :

  • Le format JSON est idéal pour l'intégration avec d'autres outils
  • L'option --output redirige la sortie vers un fichier plutôt que la console
  • Les templates personnalisés permettent de formater la sortie selon vos besoins spécifiques

Ignorer des vulnérabilités spécifiques

Il est parfois nécessaire d'ignorer certaines vulnérabilités, par exemple lorsqu'elles ne sont pas exploitables dans votre contexte ou qu'elles n'ont pas encore de correctif disponible.

bash
trivy image --ignorefile .trivyignore nginx:1.25

Le fichier .trivyignore contient les identifiants des vulnérabilités à ignorer, un par ligne :

# .trivyignore
CVE-2023-12345
CVE-2023-67890

Définir un seuil d'échec

Pour les intégrations CI/CD, vous pouvez configurer Trivy pour qu'il échoue si des vulnérabilités dépassent un certain seuil de gravité :

bash
# Échoue si des vulnérabilités HIGH ou CRITICAL sont trouvées
trivy image --exit-code 1 --severity HIGH,CRITICAL nginx:1.25

Avec cette option, la commande renvoie un code de sortie non-zéro si des vulnérabilités correspondant aux critères sont détectées, ce qui peut être utilisé pour bloquer un pipeline CI/CD.

Analyse d'images non-publiques

Pour les images stockées dans des registres privés, Trivy prend en charge l'authentification :

bash
# Authentification avec nom d'utilisateur/mot de passe
trivy image --username user --password pass registry.example.com/myapp:latest

# Utilisation des variables d'environnement
export TRIVY_USERNAME=user
export TRIVY_PASSWORD=pass
trivy image registry.example.com/myapp:latest

Ces options permettent d'analyser des images dans des registres Docker privés qui nécessitent une authentification.

Analyse d'images locales

Trivy peut également analyser des images qui n'ont pas été publiées dans un registre :

bash
# Analyser une image construite localement
docker build -t myapp:local .
trivy image myapp:local

Cette fonctionnalité est particulièrement utile pendant le développement, pour détecter les vulnérabilités avant même de pousser l'image vers un registre.

Analyse en mode cache

Pour accélérer les analyses répétées, Trivy met en cache les résultats :

bash
# Première analyse (plus lente)
trivy image nginx:1.25

# Analyses suivantes (plus rapides)
trivy image nginx:1.25

Le cache est automatiquement invalidé lorsque la base de données de vulnérabilités est mise à jour ou lorsque l'image change.

Au-delà de l'analyse basique des images Docker, Trivy offre de nombreuses fonctionnalités avancées qui en font un outil complet pour la sécurité des applications conteneurisées.

Scan de Dockerfiles

Trivy peut analyser directement les Dockerfiles pour détecter les problèmes de configuration avant même la construction de l'image :

bash
trivy config --file-type dockerfile Dockerfile

Cette analyse identifie des problèmes comme :

  • Utilisation de l'utilisateur root
  • Absence de vérification des sommes de contrôle pour les téléchargements
  • Utilisation d'images de base non spécifiques (latest)
  • Installation de packages sans nettoyage des caches

Exemple de résultat :

Dockerfile (dockerfile)
=======================
Tests: 23 (SUCCESSES: 18, FAILURES: 5, EXCEPTIONS: 0)
Failures: 5 (CRITICAL: 0, HIGH: 2, MEDIUM: 2, LOW: 1, UNKNOWN: 0)

HIGH: Specify a tag in the 'FROM' statement for image 'python'
════════════════════════════════════════════════════════════════
It is recommended to use a specific tag for the base image rather than 'latest' or no tag at all.

FROM python

────────────────────────────────────────────────────────────────

MEDIUM: Consider using a multi-stage build with a distroless or minimal base image
════════════════════════════════════════════════════════════════
Using a minimal or distroless base image can drastically reduce the attack surface and image size.

FROM python

────────────────────────────────────────────────────────────────

Scan des dépendances applicatives

Trivy peut analyser les fichiers de dépendances de nombreux écosystèmes :

bash
# Analyse des dépendances Python
trivy fs --security-checks vuln ./requirements.txt

# Analyse des dépendances Node.js
trivy fs --security-checks vuln ./package-lock.json

# Analyse des dépendances Java
trivy fs --security-checks vuln ./pom.xml

Cette fonctionnalité permet de détecter les vulnérabilités dans les dépendances avant même de construire l'image, accélérant ainsi le cycle de correction.

Analyse du code Infrastructure as Code (IaC)

Trivy peut scanner les fichiers d'infrastructure comme Terraform, Kubernetes YAML, et plus :

bash
# Scan de fichiers Kubernetes
trivy config --file-type yaml kubernetes/*.yaml

# Scan de fichiers Terraform
trivy config --file-type terraform terraform/*.tf

# Scan d'un répertoire complet avec détection automatique du type
trivy config ./infrastructure/

Cette analyse détecte les mauvaises configurations qui pourraient introduire des risques de sécurité dans votre infrastructure.

Scan du système de fichiers complet

Pour une analyse exhaustive, Trivy peut scanner un répertoire entier :

bash
# Scan d'un répertoire de projet
trivy fs --security-checks vuln,config,secret ./my-project

# Scan d'un répertoire avec exclusions
trivy fs --security-checks vuln,config,secret --skip-dirs "tests,vendor" ./my-project

Cette analyse combine la détection de vulnérabilités, les problèmes de configuration et même la détection de secrets potentiellement exposés dans le code.

Détection de secrets

Trivy peut identifier les secrets potentiellement exposés dans votre code :

bash
trivy fs --security-checks secret ./my-project

Cette fonctionnalité détecte :

  • Clés API
  • Jetons d'accès
  • Clés privées
  • Mots de passe codés en dur
  • Certificats

Analyse continue avec mode client-serveur

Pour les environnements à haut volume, Trivy peut fonctionner en mode client-serveur :

bash
# Démarrer le serveur Trivy
trivy server --listen 0.0.0.0:4954

# Utiliser un client pour interroger le serveur
trivy client --remote http://server:4954 image nginx:1.25

Ce mode permet de centraliser la base de données de vulnérabilités et d'accélérer les analyses dans les environnements CI/CD à haut débit.

Personnalisation des politiques

Trivy permet de définir des politiques personnalisées avec Rego (Open Policy Agent) :

bash
# Structure de répertoire pour les politiques personnalisées
mkdir -p trivy-policies/custom
cat > trivy-policies/custom/no-root.rego << 'EOF'
package custom

deny[res] {
  input.type == "dockerfile"
  not contains(input.contents, "USER ")
  
  res := {
    "msg": "Dockerfile must set a non-root user with USER instruction",
    "severity": "HIGH"
  }
}
EOF

# Utilisation des politiques personnalisées
trivy config --policy ./trivy-policies Dockerfile

Cette fonctionnalité permet d'adapter Trivy à vos exigences spécifiques de sécurité et de conformité.

Analyse du SBOM (Software Bill of Materials)

Trivy peut générer et analyser un SBOM (Software Bill of Materials) pour vos applications :

bash
# Génération d'un SBOM au format CycloneDX
trivy image --format cyclonedx nginx:1.25 > sbom.json

# Analyse d'un SBOM existant
trivy sbom sbom.json

Le SBOM est un inventaire formel de tous les composants logiciels et de leurs dépendances, de plus en plus exigé dans les contextes réglementaires et de sécurité.

Ces fonctionnalités avancées font de Trivy un outil complet et polyvalent pour sécuriser l'ensemble du cycle de vie des applications conteneurisées, de l'écriture du code au déploiement en production.

L'intégration de Trivy dans un pipeline CI/CD permet d'automatiser la détection des vulnérabilités et d'empêcher le déploiement d'images non sécurisées. Voici comment mettre en place cette intégration dans différents environnements.

Principes généraux d'intégration

Quelle que soit la plateforme CI/CD utilisée, certains principes s'appliquent généralement :

  1. Exécution précoce : Analysez les images dès leur construction pour détecter les problèmes au plus tôt.
  2. Seuils de gravité : Définissez des seuils d'échec en fonction de la gravité des vulnérabilités (ex: bloquer pour CRITICAL, avertir pour HIGH).
  3. Exceptions documentées : Si certaines vulnérabilités sont ignorées, documentez clairement pourquoi.
  4. Rapports automatisés : Générez des rapports dans un format qui peut être facilement consultable et archivé.
  5. Mise en cache : Utilisez les fonctionnalités de mise en cache pour accélérer les analyses.

Intégration avec GitHub Actions

Voici un exemple de workflow GitHub Actions utilisant Trivy :

yaml
name: Docker Security Scan

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .
      
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'
      
      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v2
        if: always()  # Ensures this step runs even if Trivy finds vulnerabilities
        with:
          sarif_file: 'trivy-results.sarif'

Ce workflow :

  1. Construit l'image Docker à partir de votre Dockerfile
  2. Exécute Trivy pour analyser les vulnérabilités CRITICAL et HIGH
  3. Échoue si de telles vulnérabilités sont trouvées (exit-code: '1')
  4. Télécharge les résultats au format SARIF dans l'onglet Sécurité de GitHub

Intégration avec GitLab CI/CD

Exemple de configuration .gitlab-ci.yml :

yaml
stages:
  - build
  - scan
  - deploy

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

vulnerability_scan:
  stage: scan
  image: aquasec/trivy:latest
  variables:
    TRIVY_USERNAME: $CI_REGISTRY_USER
    TRIVY_PASSWORD: $CI_REGISTRY_PASSWORD
    TRIVY_NO_PROGRESS: "true"
  script:
    - trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - trivy image --exit-code 0 --severity HIGH --output trivy-report.html --format template --template "@/contrib/html.tpl" $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  artifacts:
    paths:
      - trivy-report.html
    expire_in: 1 week
  allow_failure: false  # Bloque le pipeline si des vulnérabilités CRITICAL sont trouvées

deploy:
  stage: deploy
  script:
    - kubectl set image deployment/myapp container=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main

Cette configuration :

  1. Construit et pousse l'image vers le registre GitLab
  2. Exécute Trivy en deux passes :
    • Une première qui échoue en cas de vulnérabilités CRITICAL
    • Une seconde qui génère un rapport HTML pour les vulnérabilités HIGH
  3. Conserve le rapport comme artefact du pipeline
  4. Ne déploie l'application que si le scan de vulnérabilités réussit

Intégration avec Jenkins

Voici un exemple de Jenkinsfile :

groovy
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:${BUILD_NUMBER} .'
            }
        }
        
        stage('Scan') {
            steps {
                // Scan pour les vulnérabilités CRITICAL (bloquant)
                sh 'trivy image --exit-code 1 --severity CRITICAL myapp:${BUILD_NUMBER}'
            }
            post {
                always {
                    // Génération d'un rapport complet (non-bloquant)
                    sh 'trivy image --format json --output trivy-report.json myapp:${BUILD_NUMBER}'
                    archiveArtifacts artifacts: 'trivy-report.json', fingerprint: true
                }
                failure {
                    echo 'La build a échoué en raison de vulnérabilités CRITICAL trouvées par Trivy'
                }
            }
        }
        
        stage('Deploy') {
            steps {
                sh 'docker tag myapp:${BUILD_NUMBER} myregistry.example.com/myapp:${BUILD_NUMBER}'
                sh 'docker push myregistry.example.com/myapp:${BUILD_NUMBER}'
                sh 'kubectl set image deployment/myapp container=myregistry.example.com/myapp:${BUILD_NUMBER}'
            }
        }
    }
}

Ce pipeline :

  1. Construit l'image Docker
  2. Exécute Trivy pour détecter les vulnérabilités CRITICAL
  3. Archive un rapport complet au format JSON
  4. Déploie l'application uniquement si aucune vulnérabilité CRITICAL n'est trouvée

Intégration avec Docker Compose pour le développement local

Pour les environnements de développement local, vous pouvez intégrer Trivy dans un workflow Docker Compose :

yaml
# docker-compose.yml
services:
  app:
    build: .
    ports:
      - "8080:8080"
    # autres configurations...

  security-scan:
    image: aquasec/trivy:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./reports:/reports
    command: >
      image --exit-code 0
      --severity HIGH,CRITICAL
      --output /reports/trivy-report.html
      --format template
      --template "@/contrib/html.tpl"
      myapp:latest

Utilisable avec :

bash
# Construire l'application
docker-compose build app

# Exécuter le scan de sécurité
docker-compose run security-scan

Cette configuration permet aux développeurs d'exécuter facilement des scans de sécurité dans leur environnement local avant de pousser le code.

Bonnes pratiques pour l'intégration CI/CD

  1. Progression des exigences : Commencez avec des seuils de gravité élevés (CRITICAL uniquement) et renforcez progressivement les exigences.

  2. Distinguer les environnements :

    • Développement : Scan informatif, non bloquant
    • Test/Staging : Bloquer pour CRITICAL
    • Production : Bloquer pour CRITICAL et HIGH
  3. Gestion des faux positifs : Utilisez les fichiers .trivyignore avec une documentation claire sur les raisons d'ignorer certaines vulnérabilités.

  4. Analyse précoce : Intégrez également des scans Trivy pour les Dockerfiles et les dépendances applicatives avant même de construire l'image.

  5. Rapports historiques : Conservez les rapports de vulnérabilités pour suivre l'évolution de la posture de sécurité au fil du temps.

  6. Notifications : Configurez des alertes pour informer l'équipe des nouvelles vulnérabilités découvertes, par exemple via Slack ou par email :

yaml
# Exemple d'intégration de notification dans GitLab CI
vulnerability_scan:
  # configuration précédente...
  after_script:
    - |
      if [ $CI_JOB_STATUS == "failed" ]; then
        curl -X POST \
          -H 'Content-type: application/json' \
          --data "{\"text\":\"❌ Vulnérabilités critiques détectées dans $CI_PROJECT_NAME ! Voir $CI_JOB_URL\"}" \
          $SLACK_WEBHOOK_URL
      fi
  1. Tests de pénétration ciblés : Pour les vulnérabilités détectées, configurez des tests de pénétration ciblés pour vérifier si elles sont réellement exploitables dans votre contexte.

L'intégration de Trivy dans vos pipelines CI/CD permet d'automatiser complètement le processus de détection et de correction des vulnérabilités, renforçant ainsi la sécurité de vos déploiements Docker.

↗
https://trivy.dev/v0.62/ecosystem/cicd/

Trivy CI/CD Integration

trivy.dev

Une fois que Trivy a identifié des vulnérabilités dans vos images Docker, l'étape suivante consiste à les corriger efficacement.

Voici les principales stratégies de remédiation.

Mise à jour des packages système

La méthode la plus simple et la plus efficace pour corriger les vulnérabilités est de mettre à jour les packages du système d'exploitation vers des versions corrigées.

Dans votre Dockerfile :

dockerfile
FROM debian:12-slim

# Avant : Peut contenir des vulnérabilités
# RUN apt-get update && apt-get install -y package1 package2

# Après : Inclut les derniers correctifs de sécurité
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y package1 package2 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

Pour les images Alpine :

dockerfile
FROM alpine:3.21

# Mise à jour proactive avec les derniers correctifs
RUN apk update && \
    apk upgrade && \
    apk add package1 package2 && \
    rm -rf /var/cache/apk/*

Mise à jour des dépendances applicatives

Pour les bibliothèques applicatives vulnérables, mettez à jour les versions dans vos fichiers de dépendances :

Python (requirements.txt) :

# Avant
flask==2.0.1     # Vulnérable
pyyaml==5.4.1    # Vulnérable

# Après
flask==2.3.3     # Corrigé
pyyaml==6.0.1    # Corrigé

Node.js (package.json) :

json
{
  "dependencies": {
    "express": "4.18.2",    // Version corrigée
    "lodash": "4.17.21"     // Version corrigée
  }
}

Utilisation d'images de base alternatives

Si une image de base contient de nombreuses vulnérabilités difficiles à corriger, envisagez de passer à une alternative plus sécurisée :

dockerfile
# Avant : Image potentiellement vulnérable
FROM ubuntu:22.04

# Après : Alternative plus légère et potentiellement plus sécurisée
FROM debian:12-slim

Ou encore mieux :

dockerfile
# Alternative minimaliste avec surface d'attaque réduite
FROM alpine:3.21

Stratégies pour les vulnérabilités sans correctif

Parfois, il n'existe pas encore de correctif pour une vulnérabilité donnée. Dans ce cas, plusieurs options s'offrent à vous :

  1. Évaluation du risque réel : Déterminez si la vulnérabilité est exploitable dans votre contexte (certaines vulnérabilités peuvent nécessiter des conditions spécifiques pour être exploitées).

  2. Isolation supplémentaire : Renforcez l'isolation du conteneur (utilisateur non-root, capabilities réduites, etc.) pour limiter l'impact potentiel.

  3. Changement de composant : Remplacez le composant vulnérable par une alternative.

  4. Désactivation de fonctionnalités : Si possible, désactivez la fonctionnalité concernée par la vulnérabilité.

Gestion des exceptions

Lorsque vous choisissez d'ignorer temporairement certaines vulnérabilités, il est essentiel de les documenter dans un fichier .trivyignore :

# .trivyignore

# Vulnérabilité dans OpenSSL non exploitable dans notre contexte
# Nécessite une interaction utilisateur directe avec la bibliothèque
# Prévu d'être corrigé dans la prochaine mise à jour majeure en juin 2025
CVE-2023-5678

# Faux positif confirmé par le mainteneur du package
# Référence : https://github.com/package/issues/1234
CVE-2023-9876

Cette approche garantit la transparence et facilite la révision périodique des exceptions.

Mise en place d'une politique de correction

Pour une gestion efficace et systématique des vulnérabilités, établissez une politique claire :

  1. Priorisation basée sur la gravité :

    • CRITICAL : Correction immédiate (24-48h)
    • HIGH : Correction dans la semaine
    • MEDIUM : Planification dans le mois
    • LOW : Évaluation lors du prochain cycle de mise à jour
  2. Révision régulière des exceptions : Passez en revue les vulnérabilités ignorées tous les mois pour vérifier si des correctifs sont disponibles.

  3. Reconstruction périodique des images : Même sans changement de code, reconstruisez régulièrement vos images pour intégrer les derniers correctifs de sécurité.

  4. Documentation des actions : Maintenez un journal des vulnérabilités corrigées et des actions entreprises.

Automatisation des corrections

Pour les environnements à grande échelle, envisagez d'automatiser la correction des vulnérabilités :

  1. Outils de mise à jour automatique :

    • Dependabot pour GitHub
    • Renovate Bot pour diverses plateformes
    • Snyk pour l'intégration CI/CD
  2. Scripts personnalisés :

    bash
    #!/bin/bash
    # Script de mise à jour automatique des images Docker
    
    # Scan pour détecter les vulnérabilités
    trivy image myapp:latest --format json --output scan-results.json
    
    # Si des vulnérabilités CRITICAL sont détectées
    if grep -q "\"Severity\":\"CRITICAL\"" scan-results.json; then
      # Reconstruire l'image avec les derniers packages
      docker build --no-cache -t myapp:latest .
      
      # Vérifier si les vulnérabilités ont été corrigées
      trivy image myapp:latest --severity CRITICAL --exit-code 1 || echo "Des vulnérabilités persistent!"
    fi
    
  3. Pipeline de mise à jour automatique : Créez un pipeline dédié qui s'exécute périodiquement, construit une nouvelle version de l'image avec les derniers packages, et la déploie automatiquement si les tests de sécurité réussissent.

Surveillance continue

Au-delà de la correction ponctuelle, mettez en place un système de surveillance continue pour détecter rapidement les nouvelles vulnérabilités :

  1. Scans périodiques : Configurez des jobs pour scanner régulièrement vos images déployées.

  2. Intégration avec vos systèmes de monitoring : Envoyez les alertes de vulnérabilités à vos systèmes de surveillance existants.

  3. Tableaux de bord de sécurité : Créez des visualisations qui montrent l'évolution de votre posture de sécurité au fil du temps.

Une approche proactive et systématique de la correction des vulnérabilités est essentielle pour maintenir un niveau de sécurité élevé dans vos environnements conteneurisés. En combinant des outils comme Trivy avec des processus bien définis, vous pouvez réduire considérablement le risque d'exploitation de vulnérabilités connues.

↗
https://trivy.dev/v0.22.0/vulnerability/examples/filter/

Trivy Vulnerability Filtering

trivy.dev
  1. 1

    Étape 1 : Installation de Trivy

    Commençons par installer Trivy dans notre environnement :

    bash
    mkdir -p ~/trivy-demo && cd ~/trivy-demo
    
    wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
    echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
    sudo apt-get update
    sudo apt-get install trivy
    
    

    Alternative : utilisation via Docker

    bash
    docker pull aquasec/trivy:latest
    
  2. 2

    Étape 2 : Analyser une image publique

    Analysons une image populaire pour identifier les vulnérabilités.

    Analyse de base :

    bash
    trivy image nginx:1.25
    

    Filtrage par gravité et format de sortie :

    bash
    trivy image --severity HIGH,CRITICAL --format table nginx:1.25
    

    Observez le rapport de vulnérabilités généré. Il liste les CVE détectés, leur gravité, les versions affectées et les versions corrigées lorsqu'elles sont disponibles.

  3. 3

    Étape 3 : Création d'une image Docker vulnérable

    Créons intentionnellement une image avec des vulnérabilités pour pratiquer l'analyse et la correction.

    Création d'un Dockerfile avec des anciens packages :

    bash
    cat > Dockerfile.vulnerable << 'EOF'
    FROM debian:10
    
    RUN apt-get update && \
        apt-get install -y python3 python3-pip openssl && \
        pip3 install flask==2.0.1 requests==2.25.1
    
    COPY app.py /app/
    WORKDIR /app
    ENTRYPOINT ["python3", "app.py"]
    EOF
    

    Création d'une application Python simple :

    bash
    cat > app.py << 'EOF'
    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        return "Hello, World!"
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=5000)
    EOF
    

    Construction de l'image :

    bash
    docker build -t vulnerable-app:1.0 -f Dockerfile.vulnerable .
    
  4. 4

    Étape 4 : Analyse de l'image vulnérable

    Maintenant, analysons notre image pour identifier les vulnérabilités.

    Analyse complète :

    bash
    trivy image vulnerable-app:1.0
    

    Export au format JSON pour analyse ultérieure :

    bash
    trivy image --format json --output vulnerable-report.json vulnerable-app:1.0
    

    Cette commande va montrer de nombreuses vulnérabilités, car nous utilisons intentionnellement Debian 10 (une version ancienne) et des versions datées de packages Python.

  5. 5

    Étape 5 : Création d'une version corrigée

    Créons maintenant une version améliorée qui corrige plusieurs des vulnérabilités identifiées :

    bash
    cat > Dockerfile.fixed << 'EOF'
    FROM debian:12-slim
    
    RUN apt-get update && \
        apt-get upgrade -y && \
        apt-get install -y python3 python3-pip && \
        pip3 install flask==2.3.3 requests==2.31.0 && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/* /root/.cache
    
    RUN useradd -m -s /bin/bash appuser
    USER appuser
    
    COPY --chown=appuser:appuser app.py /app/
    WORKDIR /app
    ENTRYPOINT ["python3", "app.py"]
    EOF
    

    Construction de l'image corrigée :

    bash
    docker build -t fixed-app:1.0 -f Dockerfile.fixed .
    
  6. 6

    Étape 6 : Analyse comparative

    Analysons la nouvelle image pour voir l'amélioration.

    Analyse de l'image corrigée :

    bash
    trivy image fixed-app:1.0
    

    Comparaison des deux rapports :

    bash
    trivy image --severity HIGH,CRITICAL vulnerable-app:1.0
    trivy image --severity HIGH,CRITICAL fixed-app:1.0
    

    Vous devriez observer une réduction significative des vulnérabilités, particulièrement dans les catégories HIGH et CRITICAL.

  7. 7

    Étape 7 : Utilisation de .trivyignore

    Parfois, certaines vulnérabilités ne peuvent pas être immédiatement corrigées. Créons un fichier .trivyignore pour filtrer les faux positifs ou les vulnérabilités acceptées.

    Identifier quelques CVE à ignorer depuis le rapport précédent :

    bash
    CVE_ID=$(trivy image fixed-app:1.0 --format json | jq -r '.Results[0].Vulnerabilities[0].VulnerabilityID')
    

    Création du fichier .trivyignore :

    bash
    echo "# Vulnérabilité non exploitable dans notre contexte" > .trivyignore
    echo "$CVE_ID" >> .trivyignore
    

    Analyse avec exclusions :

    bash
    trivy image --ignorefile .trivyignore fixed-app:1.0
    
  8. 8

    Étape 8 : Scan d'un Dockerfile

    Trivy peut également analyser directement les Dockerfiles.

    Analyse du Dockerfile vulnérable :

    bash
    trivy config --file-type dockerfile Dockerfile.vulnerable
    

    Analyse du Dockerfile corrigé :

    bash
    trivy config --file-type dockerfile Dockerfile.fixed
    

    Cette analyse détecte les problèmes de configuration comme l'utilisation de l'utilisateur root, les tags non spécifiques, etc.

  9. 9

    Étape 9 : Simulation d'un pipeline CI/CD

    Créons un script simple qui simule un pipeline CI/CD avec vérification de sécurité :

    bash
    cat > ci-pipeline.sh << 'EOF'
    
    set -e
    
    echo "Étape 1: Construction de l'image"
    docker build -t ci-app:latest -f Dockerfile.fixed .
    
    echo "Étape 2: Scan de sécurité"
    
    if ! trivy image --exit-code 1 --severity CRITICAL ci-app:latest; then
      echo "❌ Test de sécurité échoué - Vulnérabilités CRITICAL détectées"
      exit 1
    fi
    
    echo "✅ Test de sécurité CRITICAL réussi"
    
    trivy image --exit-code 0 --severity HIGH --output high-vulns.txt ci-app:latest
    
    echo "Étape 3: Déploiement (simulé)"
    echo "🚀 L'image serait déployée ici dans un environnement réel"
    EOF
    

    Rendez le script exécutable et lancez-le :

    bash
    chmod +x ci-pipeline.sh
    bash ci-pipeline.sh
    

    Ce script simule un pipeline CI/CD basique qui :

    1. Construit l'image Docker
    2. Exécute Trivy pour bloquer le déploiement si des vulnérabilités CRITICAL sont détectées
    3. Génère un rapport des vulnérabilités HIGH (sans bloquer)
    4. Simule un déploiement
  10. 10

    Étape 10 : Analyse des dépendances applicatives

    Créons un fichier requirements.txt plus complet pour analyser les vulnérabilités des dépendances :

    bash
    cat > requirements-vuln.txt << 'EOF'
    flask==2.0.1
    requests==2.25.1
    Werkzeug==2.0.0
    Jinja2==3.0.0
    PyYAML==5.4.1
    cryptography==3.4.0
    EOF
    

    Scan des dépendances Python :

    bash
    trivy fs --security-checks vuln ./requirements-vuln.txt
    

    Cette analyse identifie les vulnérabilités spécifiques aux packages Python, indépendamment du système d'exploitation sous-jacent.

  11. 11

    Étape 11 : Création d'un rapport de sécurité

    Générons un rapport détaillé combinant plusieurs types d'analyses :

    bash
    cat > security-report.sh << 'EOF'
    
    IMAGE_NAME="fixed-app:1.0"
    REPORT_DIR="security-reports"
    mkdir -p $REPORT_DIR
    
    echo "Génération du rapport de sécurité pour $IMAGE_NAME"
    echo "=================================================="
    
    echo "1. Analyse de l'image Docker"
    trivy image --format json --output $REPORT_DIR/image-vulnerabilities.json $IMAGE_NAME
    
    echo "2. Analyse du Dockerfile"
    trivy config --format json --output $REPORT_DIR/dockerfile-issues.json --file-type dockerfile Dockerfile.fixed
    
    echo "3. Analyse des dépendances applicatives"
    trivy fs --format json --output $REPORT_DIR/dependencies-issues.json --security-checks vuln ./requirements-vuln.txt
    
    echo "4. Création du résumé"
    echo "Résumé du rapport de sécurité - $(date)" > $REPORT_DIR/summary.txt
    echo "----------------------------------------" >> $REPORT_DIR/summary.txt
    echo "Image: $IMAGE_NAME" >> $REPORT_DIR/summary.txt
    echo "" >> $REPORT_DIR/summary.txt
    
    echo "Vulnérabilités par niveau de gravité:" >> $REPORT_DIR/summary.txt
    CRITICAL=$(cat $REPORT_DIR/image-vulnerabilities.json | grep -c '"Severity":"CRITICAL"')
    HIGH=$(cat $REPORT_DIR/image-vulnerabilities.json | grep -c '"Severity":"HIGH"')
    MEDIUM=$(cat $REPORT_DIR/image-vulnerabilities.json | grep -c '"Severity":"MEDIUM"')
    LOW=$(cat $REPORT_DIR/image-vulnerabilities.json | grep -c '"Severity":"LOW"')
    
    echo "- CRITICAL: $CRITICAL" >> $REPORT_DIR/summary.txt
    echo "- HIGH: $HIGH" >> $REPORT_DIR/summary.txt
    echo "- MEDIUM: $MEDIUM" >> $REPORT_DIR/summary.txt
    echo "- LOW: $LOW" >> $REPORT_DIR/summary.txt
    
    echo "Rapport complet généré dans le répertoire: $REPORT_DIR"
    EOF
    

    Rendez le script exécutable et lancez-le :

    bash
    chmod +x security-report.sh
    bash security-report.sh
    

    Ce script génère un rapport de sécurité complet qui combine l'analyse de l'image Docker, du Dockerfile et des dépendances applicatives.

quiz
true||true|||true
# Quelle commande permet d'analyser les vulnérabilités d'une image Docker avec Trivy ?
[] trivy scan docker-image nginx:latest
[x] trivy image nginx:latest
[] trivy analyze --type image nginx:latest
[] trivy docker --image nginx:latest

# Comment Trivy classifie-t-il les vulnérabilités par ordre de gravité décroissante ?
[] SEVERE, HIGH, MEDIUM, LOW
[x] CRITICAL, HIGH, MEDIUM, LOW
[] FATAL, ERROR, WARNING, INFO
[] BLOCKER, MAJOR, MINOR, INFO

# Quel fichier permet d'ignorer certaines vulnérabilités lors d'un scan Trivy ?
[] trivy.ignore
[] .scanignore
[x] .trivyignore
[] .securityignore

# Quelle option de commande Trivy est utile dans un pipeline CI/CD pour faire échouer le build en cas de vulnérabilités ?
[] --fail-on-vuln
[] --block-if-vulnerable
[x] --exit-code 1
[] --strict-mode

# Outre les images Docker, que peut scanner Trivy ?
[] Uniquement des conteneurs en cours d'exécution
[] Seulement des registres Docker comme DockerHub
[x] Des Dockerfiles, des fichiers de dépendances et des configurations IaC
[] Uniquement les systèmes de fichiers locaux

💪 Challenge

Ce challenge consiste à sécuriser un Dockerfile volontairement rempli de mauvaises pratiques de sécurité, tout en conservant la fonctionnalité de l'application.


🧩 Objectifs

  1. Analyser un Dockerfile vulnérable avec Trivy
  2. Identifier les problèmes de sécurité présents
  3. Créer une version sécurisée du Dockerfile
  4. Documenter les améliorations apportées
  5. Fournir un dépôt de code contenant ta réponse (sous github ou gitlab.com)

⚙️ Code fourni

Voici le code de l'application Flask à conteneuriser :

python
# app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, World! Je suis une application Flask sécurisée."

@app.route('/health')
def health():
    return "OK", 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Et un fichier de dépendances basique :

# requirements.txt
flask==2.0.1

Voici le Dockerfile à sécuriser (rempli de mauvaises pratiques) :

dockerfile
# Dockerfile.vulnerable
FROM ubuntu:latest

# Installation des dépendances
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y python3-pip
RUN apt-get install -y curl wget vim netcat
RUN pip3 install flask==2.0.1
RUN pip3 install pytest requests

# Configuration de l'environnement
ENV DB_PASSWORD="super_secret_password123"
ENV API_KEY="A1B2C3D4E5F6G7H8I9J0"

# Copie du code
COPY . /app/

# Définir le répertoire de travail
WORKDIR /app

# Exposer le port
EXPOSE 5000

# Commande de démarrage
CMD ["python3", "app.py"]

📋 Étapes à réaliser

  1. Analyse initiale :

    • Créer un répertoire de travail contenant les fichiers fournis
    • Utiliser Trivy pour analyser le Dockerfile vulnérable
    • Identifier les problèmes de sécurité
  2. Création d'une version sécurisée :

    • Créer un nouveau Dockerfile (Dockerfile.secure)
    • Corriger toutes les mauvaises pratiques identifiées
    • S'assurer que l'application reste fonctionnelle
  3. Vérification :

    • Construire les deux images (vulnérable et sécurisée)
    • Analyser les deux images avec Trivy
    • Comparer les résultats
  4. Documentation :

    • Créer un fichier README.md expliquant les problèmes corrigés
    • Justifier les choix techniques effectués

🛠️ Indices

  • Pensez à utiliser :

    • Une image de base minimale et avec une version spécifique
    • Un build multi-étapes
    • Un utilisateur non-root
    • Une gestion sécurisée des secrets
    • La réduction du nombre de couches
    • L'élimination des packages non nécessaires
  • Commandes Trivy utiles :

    bash
    trivy config --file-type dockerfile Dockerfile.vulnerable
    trivy image vulnerable-app:latest
    

🔎 Critères d'acceptation

  1. Correction complète :

    • Aucune vulnérabilité CRITICAL dans l'image finale
    • Réduction significative des vulnérabilités HIGH
    • Correction de tous les problèmes de configuration identifiés par Trivy
  2. Application fonctionnelle :

    • L'application doit démarrer correctement
    • Les endpoints / et /health doivent être accessibles
  3. Documentation claire :

    • Liste des problèmes identifiés dans le Dockerfile initial
    • Explication des corrections apportées
    • Résultats des analyses Trivy avant/après