15 KiB
TP5 - Sécurité des conteneurs
Exercice 1 : Installation et premier scan avec Trivy
Analyse des résultats du scan de l'image python:3.9-alpine
Lors de l'exécution de Trivy sur l'image python:3.9-alpine
, l'outil a scanné différentes couches et composants de l'image pour y détecter d'éventuelles vulnérabilités.
Résumé du rapport
Le scan a identifié un total de 4 vulnérabilités :
- 1 vulnérabilité dans le système d'exploitation Alpine Linux (version 3.21.3)
- 3 vulnérabilités dans les packages Python installés
Vulnérabilités du système d'exploitation (Alpine 3.21.3)
Bibliothèque | Vulnérabilité | Sévérité | Statut | Version installée | Version corrigée | Description |
---|---|---|---|---|---|---|
sqlite-libs | CVE-2025-29087 | HAUTE | corrigée | 3.48.0-r0 | 3.48.0-r1 | Dépassement d'entier dans la fonction concat_ws de SQLite |
Vulnérabilités des packages Python
Bibliothèque | Vulnérabilité | Sévérité | Statut | Version installée | Version corrigée | Description |
---|---|---|---|---|---|---|
pip | CVE-2023-5752 | MOYENNE | corrigée | 23.0.1 | 23.3 | Configuration Mercurial injectable lors de l'installation via pip |
setuptools | CVE-2022-40897 | HAUTE | corrigée | 58.1.0 | 65.5.1 | Déni de service par expression régulière (ReDoS) dans package_index.py |
setuptools | CVE-2024-6345 | HAUTE | corrigée | 58.1.0 | 70.0.0 | Exécution de code à distance via les fonctions de téléchargement dans le module package_index |
Exercice 2 : Analyser différentes images
2.1 Comparer des images avec différentes versions
Suite à l'analyse des trois images nginx (1.14, 1.22 et latest), voici les résultats comparatifs :
Résumé des vulnérabilités par image
Image | OS de base | Vulnérabilités totales | CRITICAL | HIGH | MEDIUM | LOW | UNKNOWN |
---|---|---|---|---|---|---|---|
nginx:1.14 | debian 9.8 | 217 | 32 | 81 | 54 | 43 | 7 |
nginx:1.22 | debian 11.6 | 344 | 12 | 74 | 124 | 130 | 4 |
nginx:latest | debian 12.10 | 154 | 2 | 12 | 39 | 99 | 2 |
Analyse des résultats
-
Évolution des versions:
- L'image la plus ancienne (nginx:1.14) présente moins de vulnérabilités totales que la version intermédiaire (nginx:1.22), mais comporte significativement plus de vulnérabilités critiques et de haute sévérité.
- L'image la plus récente (nginx:latest) contient globalement le moins de vulnérabilités, surtout en termes de vulnérabilités critiques et de haute sévérité.
-
Distribution des vulnérabilités:
- nginx:1.14 (Debian 9.8): Concentration de vulnérabilités de haute sévérité et critiques (113 sur 217, soit 52%)
- nginx:1.22 (Debian 11.6): Grande quantité de vulnérabilités de moyenne et faible sévérité (254 sur 344, soit 74%)
- nginx:latest (Debian 12.10): Majorité de vulnérabilités de faible sévérité (99 sur 154, soit 64%)
-
Observations importantes:
- La version 1.22 montre un nombre total de vulnérabilités plus élevé que la version 1.14, ce qui peut sembler contre-intuitif. Cela s'explique par:
- Un système de détection plus avancé pour les versions plus récentes
- Une base de données de vulnérabilités enrichie au fil du temps
- Des bibliothèques plus récentes exposant davantage de vulnérabilités connues mais de moindre gravité
- La version latest (actuellement basée sur Debian 12.10) présente une nette amélioration en termes de vulnérabilités critiques et de haute sévérité.
- La version 1.22 montre un nombre total de vulnérabilités plus élevé que la version 1.14, ce qui peut sembler contre-intuitif. Cela s'explique par:
Risques liés à l'utilisation du tag "latest"
Utiliser le tag "latest" est risqué pour plusieurs raisons :
-
Manque de traçabilité et de reproductibilité: Le tag "latest" pointe vers la dernière version publiée, qui change au fil du temps. Cela signifie que deux déploiements à des moments différents peuvent utiliser des images différentes, rendant les déploiements non reproductibles.
-
Mises à jour automatiques non contrôlées: L'utilisation de "latest" peut entraîner des mises à jour imprévues lors du redéploiement, pouvant causer des incompatibilités ou des régressions sans préavis.
-
Incertitude de sécurité: Bien que dans cet exemple spécifique "latest" semble plus sécurisé, ce n'est pas toujours le cas. Les nouvelles versions peuvent introduire de nouvelles vulnérabilités non encore détectées.
-
Instabilité potentielle: Les versions "latest" n'ont pas nécessairement la même stabilité que les versions balisées spécifiquement.
-
Difficultés pour auditer la sécurité: Sans version fixe, il est difficile de maintenir un registre des vulnérabilités connues et de leur état de correction pour l'image utilisée.
2.2 Analyse d'une image personnalisée
L'analyse de notre image personnalisée basée sur Ubuntu 20.04 avec Flask et Requests révèle un profil de sécurité préoccupant. L'image présente un total impressionnant de 1338 vulnérabilités au niveau du système d'exploitation, majoritairement de sévérité moyenne (1235), avec une vulnérabilité de haute sévérité et 102 de faible sévérité. Au niveau des packages Python, 8 vulnérabilités ont été identifiées, dont 3 de haute sévérité. Flask 1.1.1 est affecté par une vulnérabilité permettant potentiellement la divulgation de cookies de session. La bibliothèque requests 2.22.0 présente deux vulnérabilités moyennes liées à la gestion des en-têtes HTTP et à la vérification des certificats. La dépendance urllib3 est particulièrement problématique avec 4 vulnérabilités, dont deux de haute sévérité concernant la gestion des en-têtes lors des redirections cross-origin. Ce nombre élevé de vulnérabilités s'explique principalement par l'utilisation d'une image de base complète (Ubuntu) plutôt qu'une distribution minimaliste, et par l'emploi de versions obsolètes des bibliothèques Python. Pour améliorer la sécurité, il serait judicieux d'utiliser une image Alpine plus légère, de mettre à jour les dépendances Python vers des versions récentes, et d'implémenter des pratiques comme le nettoyage des caches et la construction en multi-étapes.
Exercice 3 : Personnalisation des scans
3.1 Filtrer les résultats par sévérité
Pour filtrer les résultats du scan Trivy et n'afficher que les vulnérabilités de sévérité HIGH pour l'image nginx:latest, il faut utiliser l'option --severity
. La commande complète est :
sudo docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image --severity HIGH nginx:latest
Cette commande permet de cibler uniquement les vulnérabilités critiques, facilitant ainsi la priorisation des corrections à apporter.
3.2 Exporter les résultats dans différents formats
Trivy permet d'exporter les résultats de scan dans différents formats pour faciliter leur analyse et leur intégration dans d'autres outils.
Export au format JSON
Pour exporter les résultats du scan de nginx:latest au format JSON :
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd)/reports:/reports \
aquasec/trivy image nginx:latest \
-f json -o /reports/nginx-scan.json
Cette commande crée un fichier JSON contenant tous les détails du scan dans le dossier reports
de votre répertoire courant.
Export au format HTML
Pour générer un rapport au format HTML, plus lisible pour les utilisateurs non techniques :
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd)/reports:/reports \
aquasec/trivy image nginx:latest \
-f template --template "@contrib/html.tpl" -o /reports/nginx-scan.html
Le rapport HTML généré offre une visualisation graphique des vulnérabilités, facilitant leur compréhension et leur communication aux équipes concernées.
Note importante : Les rapports sont générés à l'intérieur du container dans le dossier /reports
qui est monté depuis votre machine hôte. Assurez-vous que le dossier reports
existe sur votre machine avant d'exécuter ces commandes.
Exercice 4 : Correction des vulnérabilités
4.1 Identifier les corrections possibles
Suite à l'analyse de notre image personnalisée basée sur Ubuntu 20.04 avec Flask et Requests, plusieurs vulnérabilités ont été identifiées. Voici les corrections possibles pour chacune d'entre elles :
Vulnérabilités du système d'exploitation (Ubuntu 20.04)
L'image présente 1338 vulnérabilités au niveau du système d'exploitation, majoritairement de sévérité moyenne. Pour corriger ces problèmes :
- Mise à jour vers Ubuntu 22.04 LTS : Cette version plus récente corrige de nombreuses vulnérabilités présentes dans la version 20.04.
- Application des mises à jour de sécurité : Utiliser
apt-get update && apt-get upgrade -y
dans le Dockerfile pour s'assurer que tous les packages sont à jour. - Nettoyage des caches apt : Réduire la surface d'attaque en supprimant les fichiers temporaires avec
apt-get clean && rm -rf /var/lib/apt/lists/*
. - Alternative : Utiliser une distribution plus légère comme Alpine Linux qui présente généralement moins de vulnérabilités en raison de sa surface d'attaque réduite.
Vulnérabilités des packages Python
-
Flask 1.1.1 (vulnérabilité permettant la divulgation de cookies de session)
- Mise à jour vers Flask 2.3.3 ou supérieur qui corrige cette vulnérabilité
- La version 2.0.0+ a considérablement amélioré la sécurité des cookies de session
-
Requests 2.22.0 (deux vulnérabilités moyennes)
- Mise à jour vers Requests 2.31.0 qui corrige les problèmes liés à la gestion des en-têtes HTTP et la vérification des certificats
- Alternativement, utiliser httpx comme bibliothèque HTTP moderne avec de meilleures pratiques de sécurité par défaut
-
urllib3 (dépendance indirecte avec 4 vulnérabilités)
- S'assurer que la mise à jour de Requests entraîne l'utilisation d'une version récente de urllib3 (2.0.0+)
- Vérifier explicitement la version de urllib3 installée avec pip freeze après la mise à jour
4.2 Mettre à jour le Dockerfile
Le Dockerfile d'origine :
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y python3 python3-pip
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY app.py .
CMD ["python3", "app.py"]
Le Dockerfile amélioré (version 4.2) :
FROM ubuntu:22.04
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y python3 python3-pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
COPY app.py .
USER nobody
EXPOSE 5000
CMD ["python3", "app.py"]
Améliorations apportées dans la version 4.2 :
-
Mise à jour de l'image de base : Passage d'Ubuntu 20.04 à Ubuntu 22.04, réduisant significativement le nombre de vulnérabilités du système d'exploitation.
-
Application des mises à jour de sécurité : Ajout de
apt-get upgrade -y
pour installer toutes les mises à jour de sécurité disponibles. -
Nettoyage des caches : Utilisation de
apt-get clean && rm -rf /var/lib/apt/lists/*
pour réduire la taille de l'image et éliminer des vecteurs d'attaque potentiels. -
Organisation du filesystem : Ajout d'un
WORKDIR /app
pour isoler les fichiers de l'application dans un répertoire dédié. -
Optimisation des installations pip : Utilisation du flag
--no-cache-dir
pour réduire la taille de l'image. -
Sécurité par principe du moindre privilège : Utilisation de
USER nobody
pour exécuter l'application avec un utilisateur non privilégié plutôt qu'avec root. -
Documentation des ports : Ajout de
EXPOSE 5000
pour documenter le port utilisé par l'application.
Mise à jour du fichier requirements.txt :
Version originale :
flask==1.1.1
requests==2.22.0
Version mise à jour :
flask==2.3.3
requests==2.31.0
Ces mises à jour corrigent les vulnérabilités identifiées dans les deux packages principaux et leurs dépendances.
4.3 Appliquer le principe des images minimales
Le Dockerfile suivant (version 4.3) applique le principe des images minimales en utilisant Alpine Linux comme base :
FROM python:3.11-alpine
WORKDIR /app
# Installer les dépendances
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
# Créer un utilisateur non privilégié
RUN adduser -D appuser
USER appuser
# Exposer le port sur lequel l'application s'exécute
EXPOSE 5000
CMD ["python3", "app.py"]
Améliorations apportées dans la version 4.3 :
-
Utilisation d'une image de base minimaliste : L'image python:3.11-alpine est basée sur Alpine Linux, une distribution ultra-légère (5-10 MB contre 180+ MB pour Ubuntu). Cette image contient déjà Python préinstallé, éliminant le besoin d'installer Python via apt.
-
Réduction drastique de la surface d'attaque : Alpine Linux utilise musl libc au lieu de glibc et contient significativement moins de packages par défaut, réduisant ainsi le nombre de vulnérabilités potentielles.
-
Création d'un utilisateur dédié : Utilisation de la commande Alpine
adduser -D appuser
pour créer un utilisateur non privilégié spécifique à l'application plutôt que d'utiliser le compte générique "nobody". -
Version plus récente de Python : Utilisation de Python 3.11 qui offre des améliorations de sécurité par rapport aux versions antérieures.
Analyse comparative des images :
Aspect | Dockerfile original | Version 4.2 (Ubuntu 22.04) | Version 4.3 (Alpine) |
---|---|---|---|
Taille approximative | ~400 MB | ~350 MB | ~85 MB |
Vulnérabilités OS | 1338 | ~500-600 (estimation) | ~10-30 (estimation) |
Vulnérabilités Python | 8 | 0 (avec deps à jour) | 0 (avec deps à jour) |
Exécution en non-root | Non | Oui (nobody) | Oui (appuser dédié) |
Nettoyage des caches | Non | Oui | Oui |
Organisation du filesystem | Non | Oui | Oui |
Conclusion
La version 4.3 utilisant Alpine Linux comme image de base représente une amélioration significative en termes de sécurité par rapport aux versions précédentes :
-
Réduction massive de la surface d'attaque : Moins de packages installés signifie moins de code potentiellement vulnérable.
-
Image plus légère : Environ 85% plus petite que l'image originale, ce qui améliore les temps de déploiement et réduit les coûts de stockage et de transfert.
-
Sécurité par défaut : Utilisation d'un utilisateur dédié non privilégié, d'un répertoire de travail isolé, et des versions à jour des dépendances.
-
Meilleure maintenabilité : Image plus petite et plus simple à comprendre, facilitant les mises à jour et les audits de sécurité.
Cette approche minimaliste, combinée à des mises à jour régulières des dépendances et à l'application du principe du moindre privilège, constitue une stratégie efficace pour maintenir un niveau de sécurité élevé dans les environnements conteneurisés.