Pourquoi les processus dans les conteneurs Docker ne devraient pas s'exécuter en tant que root

0
57

Les processus dans un conteneur Docker ne doivent pas être exécutés en tant que root. Il est plus sûr d'exécuter vos applications en tant qu'utilisateur non root que vous spécifiez dans le cadre de votre Dockerfile ou lors de l'utilisation de docker run. Cela minimise les risques en présentant une surface d'attaque réduite à toutes les menaces dans votre conteneur.

Dans cet article, vous découvrirez les dangers liés à l'exécution d'applications conteneurisées en tant que root. Vous verrez également comment créer un utilisateur non root et configurer l'espacement des noms dans les situations où cela n'est pas possible.

Pourquoi l'exécution en tant que root est-elle dangereuse ?

Les conteneurs sont exécutés en tant que root par défaut. Le démon Docker s'exécute en tant que root sur votre hôte et les conteneurs en cours d'exécution seront également root.

Bien qu'il puisse sembler que root à l'intérieur du conteneur soit un utilisateur indépendant, il s'agit en fait du compte root de votre hôte. La séparation est uniquement assurée par les mécanismes d'isolation des conteneurs de Docker. Il n'y a pas de frontière physique forte ; votre conteneur est un autre processus exécuté par l'utilisateur root sur le noyau de votre hôte. Cela signifie qu'une vulnérabilité dans votre application, l'environnement d'exécution Docker ou le noyau Linux pourrait permettre à des attaquants de sortir du conteneur et d'effectuer des opérations avec privilèges root sur votre machine.

Certaines protections intégrées réduisent le risque que cela se produise. La racine à l'intérieur du conteneur n'est pas privilégiée et a des capacités restreintes. Cela empêche le conteneur d'utiliser les commandes d'administration système à moins que vous n'ajoutiez manuellement des fonctionnalités ou que vous n'utilisiez le mode privilégié lorsque vous démarrez vos conteneurs.

Malgré cette atténuation, permettre aux applications de s'exécuter en tant que root reste un danger. Tout comme vous limiteriez l'utilisation de root dans un environnement traditionnel, il est déconseillé de l'utiliser inutilement dans vos conteneurs. Vous fournissez un environnement surprivilégié qui donne aux attaquants une meilleure prise en main en cas de violation.

Exécution d'applications conteneurisées en tant qu'utilisateur non root

Il est recommandé d'exécuter les applications conteneurisées en tant qu'utilisateur standard. La plupart des logiciels n'ont pas besoin d'un accès root, donc le changement d'utilisateur fournit une couche de défense immédiate contre l'évasion du conteneur.

Vous devez créer un nouveau compte utilisateur comme l'une des dernières étapes de votre Dockerfile. Vous pouvez y parvenir avec l'instruction USER :

FROM base-image:latest RUN apt install demo-package USER demo-user:demo-group ENTRYPOINT [“demo-binary”]

Les conteneurs démarrés à partir de cette image s'exécuteront en tant qu'utilisateur de démonstration. L'utilisateur sera membre du groupe demo-group. Vous pouvez omettre le nom du groupe si vous n'avez pas besoin que l'utilisateur soit dans un groupe :

USER demo-user

Vous pouvez spécifier un ID utilisateur (UID) et un ID de groupe (GID) au lieu de names :

USER 950:950

L'attribution d'un UID et d'un GID connus est généralement la manière la plus sûre de procéder. Cela empêche l'utilisateur du conteneur d'être mappé sur un compte hôte disposant de trop de privilèges.

USER est souvent spécifié comme l'avant-dernière étape d'un Dockerfile. Cela signifie que vous pouvez toujours exécuter des opérations nécessitant root plus tôt dans la construction de l'image. L'instruction d'installation apt dans l'exemple ci-dessus a un besoin légitime de root. Si l'instruction USER était placée au-dessus, apt serait exécuté en tant qu'utilisateur de démonstration qui n'aurait pas les autorisations nécessaires. Comme les instructions Dockerfile ne s'appliquent qu'aux versions d'image, et non aux conteneurs en cours d'exécution, vous pouvez laisser le changement d'utilisateur plus tard dans votre Dockerfile.

La modification de l'utilisateur sous lequel votre conteneur s'exécute peut nécessiter la mise à jour des autorisations sur les fichiers et dossiers auxquels il accède. Définissez la propriété sur tous les chemins qui seront utilisés par votre application :

COPY initial-config.yaml /data/config.yaml USER demo-user:demo-group RUN chown demo-user:demo-group /data < p>Dans cet exemple, le répertoire /data doit appartenir à demo-user afin que l'application puisse apporter des modifications à son fichier de configuration. L'instruction COPY précédente aura copié le fichier en tant que root. Un raccourci est disponible en utilisant le drapeau –chown avec copie :

COPY –chown=demo-user:demo-group initial-config.yaml /data/config.yaml

Changer l'utilisateur lors du démarrage d'un conteneur

Bien que vous puissiez facilement changer l'utilisateur dans vos propres Dockerfiles, de nombreuses applications tierces continuent de s'exécuter en tant que root. Vous pouvez réduire le risque associé à leur utilisation en définissant l'indicateur –user chaque fois que vous appelez docker run. Cela remplace l'utilisateur défini dans le Dockerfile de l'image.

$ docker run -d –user demo-user:demo-group demo-image:latest $ docker run -d –user demo-user demo-image:latest $ docker run -d –user 950:950 demo-image :latest

L'indicateur –user exécute le processus du conteneur en tant qu'utilisateur spécifié. C'est moins sûr que l'instruction Dockerfile USER car vous devez l'appliquer individuellement à chaque commande docker run. Une meilleure option pour les images régulièrement utilisées consiste à créer votre propre image dérivée qui peut définir un nouveau compte utilisateur :

FROM image-qui-s'exécute-en-tant que-root:dernière USER demo-user $ docker build . -t image-qui-s'exécute-maintenant-en-tant-que-non-root : dernière

Changer l'utilisateur d'une image tierce peut causer des problèmes : si le conteneur s'attend à être exécuté en tant que root ou doit accéder aux chemins du système de fichiers appartenant à root, vous verrez des erreurs lorsque vous utiliserez l'application. Vous pouvez essayer de modifier manuellement les autorisations sur les chemins qui causent des problèmes. Vous pouvez également vérifier si le fournisseur dispose d'une méthode prise en charge pour exécuter l'application avec un compte d'utilisateur non privilégié.

Gestion des applications Qui doivent s'exécuter en tant que root

L'espacement des noms d'utilisateurs est une technique permettant de gérer les applications nécessitant certains privilèges root. Il vous permet de mapper root à l'intérieur d'un conteneur vers un utilisateur non root sur votre hôte. La racine simulée à l'intérieur du conteneur dispose des privilèges dont elle a besoin, mais une évasion ne fournira pas d'accès racine à l'hôte.

Le remappage de l'espace de noms est activé en ajoutant un champ userns-remap à votre fichier /etc/docker/daemon.json :

{ "userns-remap" : "default" }

L'utilisation de default comme valeur pour userns-remap indique à Docker de créer automatiquement un nouvel utilisateur sur votre hôte appelé dockremap. La racine dans les conteneurs sera mappée vers dockremap sur votre hôte. Vous pouvez éventuellement spécifier un utilisateur et un groupe existants à la place, en utilisant une combinaison UID/GID ou nom d'utilisateur/nom de groupe :

{ "userns-remap" : "demo-user" }

Redémarrez le démon Docker après avoir appliqué votre modification :

$ sudo service docker restart

Si vous utilisez nsuser-remap : default, l'utilisateur dockremap devrait maintenant exister sur votre hôte :

$ id dockremap uid=140(dockremap) gid=119(dockremap) groups=119(dockremap)

L'utilisateur doit également apparaître dans les fichiers d'ID subordonnés /etc/subuid et /etc/subgid :

$ dockremap:231500 :65535

L'utilisateur s'est vu attribuer une plage de 65 535 ID subordonnés à partir de 231500. Dans l'espace de noms d'utilisateur, l'ID 231500 est mappé sur 0, ce qui en fait l'utilisateur racine dans vos conteneurs. Étant un UID à numéro élevé, 231500 n'a aucun privilège sur l'hôte, de sorte que les attaques par évasion de conteneurs ne pourront pas infliger autant de dégâts.

Tous les conteneurs que vous démarrez s'exécuteront à l'aide de l'espace de noms d'utilisateur remappé sauf si vous vous désabonnez avec docker run –userns=host. Le mécanisme fonctionne en créant des répertoires avec espace de noms dans /var/lib/docker qui appartiennent à l'UID et au GID subordonnés de l'utilisateur avec espace de noms :

$ sudo ls -l /var/lib/docker/231500.231500 total 14 drwx—— 5 231500 231500 13 juillet 22 19:00 aufs drwx—— 3 231500 231500 13 juillet 22 19:00 conteneurs . ..

L'espacement des noms d'utilisateurs est un moyen efficace d'augmenter l'isolation des conteneurs, d'éviter les interruptions et de préserver la compatibilité avec les applications nécessitant des privilèges root. Il y a cependant quelques compromis : la fonctionnalité fonctionne mieux sur une nouvelle instance Docker, les volumes montés à partir de l'hôte doivent avoir leurs autorisations ajustées et certains pilotes de stockage externes ne prennent pas du tout en charge le mappage des utilisateurs. Vous devriez consulter la documentation avant d'adopter cette option.

Résumé

L'exécution d'applications conteneurisées en tant que root présente un risque de sécurité. Bien qu'il soit facile de l'oublier, l'isolement fourni par les conteneurs n'est pas assez fort pour séparer complètement les utilisateurs du noyau des utilisateurs du conteneur. La racine dans le conteneur est la même que la racine sur votre hôte, donc une compromission réussie pourrait fournir le contrôle de votre machine.

En tant qu'auteur d'image, vous devez inclure l'instruction USER dans votre Dockerfile afin que votre application s'exécute sans racine. Les utilisateurs d'images peuvent remplacer cela avec docker run –user pour attribuer un UID et un GID spécifiques. Cela permet d'atténuer les cas où l'image utilise normalement la racine.

Vous pouvez encore renforcer la sécurité en supprimant toutes les fonctionnalités du conteneur à l'aide de –cap-drop=ALL, puis en mettant sur liste blanche celles qui sont requises avec –cap- ajouter des drapeaux. La combinaison de ces techniques exécutera votre application en tant qu'utilisateur non root avec l'ensemble minimum de privilèges dont elle a besoin, améliorant ainsi votre posture de sécurité.

LIRE LA SUITE

  • › Il est normal de lésiner sur ces 10 produits technologiques
  • &rsaquo ; Comment ajouter des visualisations Winamp à Spotify, YouTube, etc.
  • &rsaquo ; 10 fonctionnalités cachées d'Android 13 que vous auriez pu manquer
  • &rsaquo ; Android 13 est sorti : nouveautés et date de disponibilité
  • &rsaquo ; JBL Live Free 2 Review : excellente suppression du bruit, son correct
  • › 6 choses qui ralentissent votre Wi-Fi (et que faire à leur sujet)