web-dev-qa-db-fra.com

Docker en tant que sandbox pour le code non approuvé

J'ai créé une application web qui permet entre autres d'écrire, de compiler et d'exécuter du code (Java, C #). L'application crée un conteneur Docker pour chaque utilisateur où la compilation et l'exécution du code ont lieu. J'ai pris les mesures suivantes pour sécuriser le conteneur:

  • Ce conteneur ne contient aucune donnée persistante ou partagée.
  • Il n'a pas accès à l'API Docker (qui est sécurisée avec TLS).
  • Il n'y a aucune information dans le conteneur que l'utilisateur ne devrait pas connaître.
  • L'utilisateur ne saura pas que le compilateur se trouve dans un conteneur.

Puis-je considérer ce conteneur comme sûr pour exécuter du code non approuvé? Existe-t-il des moyens connus pour affecter la machine hôte à partir du conteneur dans une configuration comme celle-ci?

38
Hartger

tl; dr : les solutions de conteneurs ne garantissent pas et ne garantiront jamais une isolation complète, utilisez plutôt la virtualisation si vous en avez besoin.

Approches ascendantes et descendantes

Docker (et il en va de même pour les solutions de conteneurs similaires) ne garantit pas une isolation complète et ne doit pas être confondu avec la virtualisation. L'isolation des conteneurs est obtenue en ajoutant certains des barrières entre eux, mais ils utilisent toujours des ressources partagées comme noyau. La virtualisation, d'autre part, a des ressources partagées beaucoup plus petites, qui sont plus faciles à comprendre et bien testées à l'heure actuelle, souvent enrichies de fonctionnalités matérielles pour restreindre l'accès. Docker lui-même le décrit dans son article de sécurité Docker comme

L'un des principaux risques liés à l'exécution de conteneurs Docker est que l'ensemble de fonctionnalités et de montages par défaut donné à un conteneur peut fournir une isolation incomplète, soit indépendamment, soit lorsqu'il est utilisé en combinaison avec des vulnérabilités du noyau.

Considérez la virtualisation comme une approche descendante

Pour la virtualisation, vous commencez par une isolation à peu près complète et fournissez certains interfaces bien gardées et bien décrites; cela signifie que vous pouvez être sûr que sortir d'une machine virtuelle est difficile. Le noyau n'est pas partagé, si vous avez un exploit du noyau vous permettant d'échapper aux restrictions des utilisateurs, l'hyperviseur est entre vous et les autres machines virtuelles.

Cela n'implique pas un isolement parfait. À maintes reprises, des problèmes d'hyperviseur sont détectés, mais la plupart d'entre eux sont des attaques très compliquées avec une portée limitée et difficiles à exécuter (mais il existe également des attaques très critiques, "faciles à exploiter").

En revanche, les conteneurs sont ascendants

Avec les conteneurs, vous commencez par exécuter des applications sur le même noyau, mais ajoutez des barrières (espaces de noms du noyau, cgroups, ...) pour mieux les isoler. Bien que cela offre certains avantages en termes de frais généraux réduits, il est beaucoup plus difficile de "être sûr" de n'avoir rien oublié, le noyau Linux est un logiciel très volumineux et complexe. Et le noyau lui-même est toujours partagé, s'il y a un exploit dans le noyau, les chances sont élevées que vous puissiez échapper à l'hôte (et/ou à d'autres conteneurs).

Utilisateurs à l'intérieur et à l'extérieur des conteneurs

Surtout avant - Docker 1.9 qui devrait obtenir les espaces de noms des utilisateurs signifie à peu près "la racine du conteneur a également les privilèges de la racine de l'hôte" dès qu'une autre barrière manquante dans la machine Docker (ou exploit du noyau) est trouvée. Il y a eu de tels problèmes auparavant , vous devriez vous attendre à plus et Docker recommande que vous

prenez soin d'exécuter vos processus à l'intérieur des conteneurs en tant qu'utilisateurs non privilégiés (c'est-à-dire non root).

Si vous êtes intéressé par plus de détails, estep a publié un bon article sur http://integratedcode.us expliquant les espaces de noms des utilisateurs .

La restriction de l'accès root (par exemple, en imposant un utilisateur non privilégié lors de la création de l'image ou au moins en utilisant les nouveaux espaces de noms des utilisateurs) est une mesure de sécurité nécessaire et de base pour assurer l'isolement, et pourrait donner satisfaisant = isolation entre les conteneurs. Utiliser des utilisateurs et des espaces de noms d'utilisateurs restreints, échapper à l'hôte devient beaucoup plus difficile, mais vous ne devez toujours pas être sûr qu'il n'y a qu'une autre façon non envisagée de sortir d'un conteneur (et si cela inclut l'exploitation d'un problème de sécurité non corrigé dans le noyau ), et ne doit pas être utilisé pour exécuter du code non approuvé.

34
Jens Erat

Alors que la réponse de @ jens-erat a le bon point de haut niveau que la virtualisation fournit une isolation supérieure aux solutions de conteneurisation comme docker, ce n'est pas un noir et configuration blanche.

D'une part, il y a eu un certain nombre de pannes d'hôtes -> Host dans la technologie de virtualisation (par exemple la vulnérabilité " Venom " dans les pilotes de périphériques de disquette virtuelle ) comme pour tout contrôle de sécurité, l'isolement fourni par la virtualisation n'est pas à 100%.

Dans la perspective de durcir votre installation de docker pour améliorer l'isolation et réduire le risque posé, vous pouvez prendre un certain nombre de mesures pour sécuriser votre installation de docker.

  1. Docker propose de bons conseils de sécurité sur le renforcement. Il y a un (légèrement désuet) Guide de sécurité CIS et aussi banc docker qui peut être utilisé pour revoir les configurations

  2. Selon le fonctionnement de votre application (c.-à-d. Comment le code y parvient-il pour la compilation), vous pouvez modifier le fonctionnement de docker pour réduire les risques d'activité malveillante. Par exemple, en supposant que le code s'y trouve au niveau de l'hôte, vous pourrez peut-être refuser l'accès réseau au conteneur (--net none allumer docker run). Vous pouvez également voir si vous pouvez supprimer des capacités supplémentaires pour réduire ce que le processus en cours d'exécution dans le conteneur peut faire.

  3. Pensez à utiliser les profils AppArmor pour limiter les ressources. AppArmor peut être utilisé pour restreindre ce qui peut être fait dans le conteneur et vous pouvez utiliser des outils comme bane pour générer des profils pour vos applications.

  4. Je recommanderais également la mise en œuvre d'une surveillance au niveau de l'hôte pour rechercher un accès potentiellement malveillant. Comme vous savez ce que les conteneurs devraient/ne devraient pas faire, une surveillance relativement stricte vous alerterait de toute rupture éventuelle

Un autre domaine qui pourrait être productif pour durcir ce type de configuration est d'utiliser des images de système d'exploitation hôte et de conteneur réduites. Moins le code est exposé, plus la surface d'attaque est petite. Quelque chose comme CoreOS ou Ubuntu Snappy Core pourrait être intéressant à regarder

12
Rory McCune

Ma solution serait quelque chose comme SmartOS. La raison pour laquelle SmartOS prend en charge Docker, KVM et les zones. Vous pouvez donc les utiliser en combinaison pour empêcher l'exécution de code malveillant au-delà d'un conteneur Docker. Après tout, les conteneurs Docker sont toujours des fichiers sur un système de fichiers.

1
Christo Goosen