Pourquoi êtes-vous ici ?
Vous voulez connaître la vraie réponse à deux questions sur la sécurité de Docker :
Docker est-il sûr pour une utilisation en production ?
Ouiet non. Docker utilise un modèle de sécurité qui repose sur les espaces de noms et l'isolation des ressources, ce qui rend les processus à l'intérieur plus sûrs contre les attaques spécifiques que l'exécution de vos applications directement à partir d'une VM cloud ou d'un système bare metal.Malgré cette couche, il existe encore de nombreux moyens pour les attaquants d'accéder à votre conteneur, ce qui leur permet de lire des informations confidentielles, d'exécuter des attaques par déni de service (DoS) ou même d'obtenir un accès racine au système hôte.
Comment puis-je améliorer ma sécurité Docker (d'une manière pas trop douloureuse) ?
Nousallons vous présenter les vulnérabilités les plus courantes et les plus graves de Docker, en passant outre les recommandations de base que vous trouverez partout sur Google, comme l'utilisation d'images officielles et la mise à jour de votre hôte.Au lieu de cela, nous vous conduirons directement vers les nouvelles options de Docker et les lignes de Dockerfile qui rendront votre nouveau déploiement de conteneurs Docker par défaut beaucoup plus sûr que jamais.

La liste de contrôle de sécurité de Docker (no-BS)
Rendre les systèmes de fichiers du conteneur accessibles en lecture seule
Que gagnez-vous ?
Vous empêchez un pirate de modifier l'environnement d'exécution de votre conteneur Docker, ce qui pourrait lui permettre de recueillir des informations utiles sur votre infrastructure, de collecter des données utilisateur ou de mener directement une attaque DOS ou par ransomware.
Comment le régler ?
Vous avez deux options, soit au moment de l'exécution, soit dans votre configuration Docker Compose.
Au moment de l'exécution : docker run --read-only votre-app:v1.0.1
Dans votre fichier Docker Compose :
services :
webapp :
image : your-app:v1.0.1read_only : true
...
Escalade des privilèges de verrouillage
Que gagnez-vous ?
Vous empêchez votre conteneur Docker - ou un attaquant qui s'amuse à l'intérieur dudit conteneur - d'activer de nouveaux privilèges, même au niveau racine, avec setuid ou setgid. Avec un accès plus permissif à votre conteneur, un attaquant pourrait accéder à des informations d'identification sous la forme de mots de passe ou de clés pour des parties connectées de votre déploiement, comme une base de données.
Comment le régler ?
Encore une fois, au moment de l'exécution ou dans votre configuration Docker Compose.
Au moment de l'exécution : docker run --security-opt=no-new-privileges your-app:v1.0.1
Dans votre fichier Docker Compose :
les services :
webapp :
image : your-app:v1.0.1
security_opt:
- no-new-privileges:true
...
Isolez vos réseaux de conteneurs à conteneurs
Que gagnez-vous ?
Par défaut, Docker laisse tous les conteneurs communiquer via le réseau docker0, ce qui peut permettre à un attaquant de se déplacer latéralement d'un conteneur compromis à un autre. Si vous avez des services discrets A
et B
dans des conteneurs Y
et Z
Si les deux parties n'ont pas besoin de communiquer directement, l'isolation de leurs réseaux offre la même expérience à l'utilisateur final tout en empêchant les mouvements latéraux pour une meilleure sécurité de Docker.
Comment le régler ?
Vous pouvez spécifier les réseaux Docker au moment de l'exécution ou dans votre configuration Docker Compose. Cependant, vous devez d'abord créer le réseau :
docker network create your-isolated-network
Au moment de l'exécution, ajoutez l'élément --option réseau
n : docker run --network your-isolated-network your-app:v1.0.1
Ou l'option équivalente dans votre fichier Docker Compose :
les services :
webapp :
image : your-app:v1.0.1
networks:
- votre-réseau-isolé
...
Définir un utilisateur non-root approprié
Que gagnez-vous ?
L'utilisateur par défaut dans un conteneur est racine
avec un uid de 0
. En spécifiant un utilisateur distinct, vous empêchez un attaquant d'escalader ses privilèges vers un autre utilisateur qui peut agir sans restriction, comme root, ce qui annulerait toutes les autres mesures de sécurité Docker que vous avez travaillé dur pour mettre en œuvre.
Comment le régler ?
Créez votre utilisateur au cours du processus de construction ou d'exécution. Lors de l'exécution, vous pouvez soit créer l'utilisateur pour la première fois, soit remplacer la fonction UTILISATEUR
que vous avez déjà défini lors de la construction.
Pendant le processus de construction, dans votre Fichier Docker
:
...
RUN groupadd -r votre-utilisateur
RUN useradd -r -g votre-utilisateur votre-utilisateur
USER mon utilisateur
...
Au moment de l'exécution : docker run -u votre-utilisateur votre-app:v1.0.1
Abandonner les capacités du noyau Linux
Que gagnez-vous ?
Par défaut, les conteneurs Docker sont autorisés à utiliser un ensemble restreint de fonctionnalités du noyau Linux. On pourrait penser que les gens de Docker ont créé cet ensemble restreint pour qu'il soit complètement sécurisé, mais de nombreuses capacités existent pour des raisons de compatibilité et de simplicité. Par exemple, les conteneurs par défaut peuvent arbitrairement changer la propriété des fichiers, modifier leur répertoire racine, manipuler les UID des processus et lire les sockets. En abandonnant tout ou partie de ces capacités, vous minimisez le nombre de vecteurs d'attaque.
Comment le régler ?
Vous pouvez supprimer des capacités et en définir de nouvelles au moment de l'exécution. Par exemple, vous pouvez supprimer toutes les capacités du noyau et n'autoriser votre conteneur qu'à modifier la propriété des fichiers existants.
docker run --cap-drop ALL --cap-add CHOWN your-app:v1.0.1
Ou pour Docker Compose :
services :
webapp :
image : your-app:v1.0.1
cap_drop:
- ALL
cap_add:
- CHOWN
...
Prévenir les bombes à fourchette
Que gagnez-vous ?
Les bombes à fourche sont un type d'attaque DoS qui réplique à l'infini un processus existant. Tout d'abord, ils réduisent les performances et limitent les ressources, ce qui augmente inévitablement les coûts et peut finalement faire planter vos conteneurs ou le système hôte. Une fois qu'une bombe à fourche a démarré, il n'y a pas d'autre moyen de l'arrêter que de redémarrer le conteneur ou le système hôte.
Comment le régler ?
Au moment de l'exécution, vous pouvez limiter le nombre de processus (PID) que votre conteneur peut créer.
docker run --pids-limit 99 votre-app:v1.0.1
Ou avec Docker Compose :
services :
webapp :
image : your-app:v1.0.1
deploy
limites:
pids : 99
Améliorez la sécurité de Docker en surveillant vos dépendances open source
Que gagnez-vous ?
Les applications que vous avez conteneurisées pour les déployer avec Docker ont probablement une large arborescence de dépendances.
Comment le régler ?
Le moyen le plus "non-BS" est l'analyse des dépendances open-source d'Aikido. Notre surveillance continue analyse les projets écrits dans plus d'une douzaine de langues en se basant sur la présence de lockfiles dans votre application et fournit une vue d'ensemble instantanée des vulnérabilités et des logiciels malveillants. Grâce au triage automatique qui filtre les faux positifs, Aikido vous donne des conseils de remédiation que vous pouvez commencer à appliquer immédiatement... et pas seulement après avoir lu une douzaine d'autres documents de référence et de problèmes GitHub.
Chez Aikido, nous aimons les projets open-source bien établis comme Trivy, Syft et Grype. Nous savons aussi par expérience que les utiliser de manière isolée n'est pas une expérience particulièrement agréable pour les développeurs. Sous le capot, Aikido améliore ces projets avec des règles personnalisées pour combler les lacunes et révéler les failles de sécurité que vous n'auriez pas pu trouver autrement. Contrairement à l'enchaînement de divers outils open-source, Aikido vous évite d'avoir à construire un script d'analyse ou à créer un travail personnalisé dans votre CI/CD.

Utiliser uniquement des images de confiance pour la sécurité de Docker
Que gagnez-vous ?
Docker Content Trust (DCT) est un système de signature et de validation du contenu et de l'intégrité des images officielles que vous tirez des registres Docker comme Docker Hub. Le fait de n'extraire que des images signées par l'auteur vous donne l'assurance qu'elles n'ont pas été modifiées pour créer des vulnérabilités dans votre déploiement.
Comment le régler ?
La méthode la plus simple consiste à définir la variable d'environnement dans votre shell, ce qui vous empêche, ainsi que toute autre personne, de travailler avec des images non fiables.
exportDOCKER_CONTENT_TRUST=1
docker run ...
Vous pouvez également définir la variable d'environnement à chaque fois que vous exécutez Docker :
DOCKER_CONTENT_TRUST=1 docker run ...
Mise à jour des durées d'exécution en fin de vie (EOL)
Que gagnez-vous ?
Une recommandation courante pour la sécurité des conteneurs Docker est d'épingler les images et les dépendances à une version spécifique au lieu de les épingler à une version spécifique. le plus récent
. En théorie, cela vous empêche d'utiliser à votre insu de nouvelles images, même celles qui ont été falsifiées, qui introduisent de nouvelles vulnérabilités.
Comment le régler ?
Vous disposez de quelques projets open-source pour vous aider à découvrir les dates de fin de vie et à vous préparer au mieux. Le projet endoflife.date(dépôt GitHub) suit plus de 300 produits en regroupant des données provenant de sources multiples et en les mettant à disposition via une API publique. Quelques options s'offrent à vous avec endoflife.date et d'autres projets similaires :
- Vérifier manuellement le projet pour les mises à jour des dépendances sur lesquelles vos applications s'appuient et créer des tickets ou des problèmes pour les mises à jour nécessaires.
- Écrire un script (Bash, Python, etc.) pour obtenir les dates de fin de vie des dépendances à partir de l'API et l'exécuter régulièrement, comme une tâche cron.
- Incorporez l'API publique, ou ce script personnalisé, dans votre plateforme CI pour faire échouer les constructions qui utilisent un projet dont la fin de vie est proche ou atteinte.
En tant que développeur, nous comprenons que votre temps est précieux et souvent limité. C'est là qu'Aikido peut vous apporter un sentiment de sécurité - notre fonction d'analyse EOL suit votre code et vos conteneurs, en priorisant les runtimes ayant le plus d'impact et d'exposition, comme Node.js ou un serveur web Nginx. Comme d'habitude, nous ne nous contentons pas d'automatiser la collecte d'informations, mais nous émettons des alertes d'une sévérité appropriée pour vous informer et non vous submerger.

Limiter l'utilisation des ressources du conteneur
Que gagnez-vous ?
Par défaut, les conteneurs n'ont pas de contraintes de ressources et utilisent autant de mémoire ou de CPU que le planificateur de l'hôte. Limiter l 'utilisation des ressources d'un conteneur spécifique peut minimiser l'impact d'une attaque par déni de service. Au lieu de faire planter votre conteneur ou votre système hôte en raison d'une exception de mémoire insuffisante, l'attaque DoS en cours n'aura qu'un impact négatif sur l'expérience de l'utilisateur final.
Comment le régler ?
Au moment de l'exécution, vous pouvez utiliser la fonction --Mémoire
et --cpus
pour définir les limites d'utilisation de la mémoire et du processeur, respectivement. L'option memory prend des nombres avec g pour gigaoctets et m pour mégaoctets, tandis que l'option CPU reflète la limite des CPU dédiés disponibles pour le conteneur et ses processus.
docker run --memory="1g" --cpus="2" votre-app:v1.0.1
Cela fonctionne également avec Docker Compose :
services :
webapp :
image : your-app:v1.0.1
deploy:
limites :
cpus : '2'
memory: 1G
...
Votre dernière commande et les options de Compose pour la sécurité de Docker
Vous avez maintenant vu un certain nombre de conseils de sécurité Docker et les options CLI pertinentes ou la configuration qui les accompagne, ce qui signifie que vous êtes soit très enthousiaste à l'idée de les mettre en œuvre, soit submergé par la façon de les assembler. Ci-dessous, nous avons regroupé toutes les recommandations en une seule commande ou un seul modèle de configuration, ce qui vous aidera à déployer des conteneurs Docker plus sûrs dès maintenant.
Il est évident que vous voudrez modifier certaines options, comme le nom de l'utilisateur non root, les capacités du noyau, les limites de ressources, en fonction des besoins de votre application.
exportDOCKER_CONTENT_TRUST=1
docker run \N--Lire la suite
--read-only (lecture seule) \N--Security-opt=no-new-privileges (sécurité)
--security-opt=no-new-privileges\N--Configuration du réseau\N--Configuration du réseau \N--Sécurité
--network your-isolated-network \N--cap-drop ALL
--cap-drop ALL
--cap-add CHOWN \N- --pids-limit 99
--pids-limit 99 \N
--memory="1g" --cpus="2" \N-user=votre-utilisateur \N--cap-drop ALL
--user=votre-utilisateur \N
... # LES AUTRES OPTIONS VONT ICI
votre-app:v1.0.1
Vous pouvez même créer un alias drun avec l'interpréteur de commandes de votre hôte que vous pouvez invoquer sans avoir à vous souvenir de tous ces détails.
function drun {
docker run \N
--read-only (lecture seule) \N-security-opt=no-new-privileges (sécurité)
--security-opt=no-new-privileges\N--concernant le réseau de votre réseau isolé\N
--network your-isolated-network \N--cap-drop ALL
--cap-drop ALL
--cap-add CHOWN \N- --pids-limit 99
--pids-limit 99 \N
--memory="1g" --cpus="2" \N-user=votre-utilisateur \N--cap-drop ALL
--user=votre-utilisateur \N
$1 \
$2
}
Ensuite, lancez votre alias comme suit, avec vos options et le nom de l'image : drun -it your-app:v1.0.1
Si vous êtes un adepte de Docker Compose, vous pouvez adapter toutes les mêmes options dans un nouveau modèle de base de Docker Compose à partir duquel vous pourrez travailler à l'avenir :
services :
webapp :
image : your-app:v1.0.1
read_only: true
security_opt:
- no-new-privileges:true
networks:
- votre-réseau-isolé
cap_drop:
- ALL
cap_add:
- CHOWN
deploy:
limits :
pids : 9
cpus: '2'
memory: 1G
... # D'AUTRES OPTIONS VONT ICI
Bonus : Exécuter Docker avec des conteneurs sans racine
Lorsque vous installez Docker sur un système, son démon fonctionne avec des privilèges de niveau racine. Même si vous activez toutes les options ci-dessus et que vous empêchez l'escalade des privilèges au sein d' un conteneur Docker, le reste de l'exécution du conteneur sur votre système hôte dispose toujours des privilèges root. Cela élargit inévitablement votre surface d'attaque.
La solution réside dans les conteneurs sans racine, qu'un utilisateur non privilégié peut créer et gérer. L'absence de privilèges root signifie beaucoup moins de problèmes de sécurité pour votre système hôte.
Nous aimerions pouvoir vous aider à utiliser des conteneurs sans racine avec une seule option ou commande, mais ce n'est pas si simple. Vous trouverez des instructions détaillées sur le site web Rootless Containers, y compris un guide pratique pour Docker.
Quelle est la prochaine étape pour votre sécurité Docker ?
Si vous avez appris quelque chose de cette expérience, c'est que la sécurité des conteneurs est une opération de longue haleine. Il y a toujours plus de checklists de renforcement et d'articles de fond à lire sur le verrouillage de vos conteneurs dans Docker ou son cousin plus ancien et souvent mal compris, Kubernetes. Vous ne pouvez pas viser une sécurité des conteneurs sans faille - créer du temps dans votre calendrier de développement chargé pour aborder la sécurité, puis apporter des améliorations incrémentales basées sur l'impact et la gravité, vous permettra d'aller loin au fil du temps.
Pour vous aider à maximiser ce processus continu et à prioriser les correctifs qui amélioreront de manière significative la sécurité de vos applications, il y a Aikido. Nous venons de lever une série A de 17 millions de dollars pour notre plateforme de sécurité pour développeurs "no BS", et nous serions ravis que vous nous rejoigniez.