Docker Evaluation
Docker Evaluation
Version 1.0
16 avril 2019
Table des matières
1 Introduction 3
1.1 Objet du document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Identification du produit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Documents applicables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Installation du produit 4
2.1 Options d’installation retenues pour le produit . . . . . . . . . . . . . . . . . . . 4
2.2 Description de l’installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4 Analyse de la conformité 17
4.1 Conformité du produit à la cible de sécurité . . . . . . . . . . . . . . . . . . . . . 17
4.1.1 Cloisonnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.1.2 Isolation des ressources . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.1.3 Restriction des privilèges . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.1.4 Limitation des accès aux ressources . . . . . . . . . . . . . . . . . . . . . . 19
7 Synthèse 32
7.1 Installation du produit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
7.2 Résistance des fonctions et mécanismes . . . . . . . . . . . . . . . . . . . . . . . . 32
7.3 Conformité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.4 Vulnérabilités . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.5 Facilité d’emploi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Annexe C MediaWiki 41
C.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
C.2 Image Docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
C.3 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Annexe D Preuve de concept CVE-2019-5736 45
Logiciel libre de gestionnaire de conteneurs
1 Introduction
1.1 Objet du document
Le présent document constitue l’évaluation BSS Express du produit Docker Community
Edition (CE) dans sa version 18.09.3, build 774a1f4 développé par Docker, Inc..
2 Installation du produit
2.1 Options d’installation retenues pour le produit
L’environnement prévu pour l’évaluation représenté à la figure 1 est une architecture trois tiers
ou à trois couches. La mise en œuvre de cet environnement est réalisée grâce à l’environnement
virtualisé VirtualBox 1 et déployé grâce à l’outil Vagrant 2 . L’installation, la configuration et
le déploiement des différents logiciels (Docker, images Docker, conteneurs applicatifs, . . .) sont
réalisés grâce à l’outil Ansible 3 .
L’installation de Vagrant est réalisée en exécutant la commande suivante après avoir téléchargé
1. [Link]
2. [Link]
3. [Link]
$ v a g r a n t p l u g i n i n s t a l l vagrant −r e l o a d
L’environnement prévu pour l’évaluation est créé lors de l’exécution de la commande suivante :
$ v a g r a n t up
Cette création se déroule en plusieurs étapes décrites dans le fichier de configuration Vagrant
appelé Vagranfile et dans les fichiers de configuration Ansible appelés playbook disponibles en
annexe A :
1. Installation de la machine virtuelle officielle Ubuntu 64bits Bionic depuis la bibliothèque
de Vagrant
2. Redirection du port 80 de la machine virtuelle sur le port 8080 de l’interface réseau locale
ou localhost de l’hôte de la machine virtuelle permettant à l’opérateur de se connecter en
HTTP à partir d’un client WEB ([Link] à la couche de traitement métier
des données, le serveur HTTP (App A)
3. Installation et configuration de Docker dans la machine virtuelle grâce au fichier de con-
figuration Ansible, [Link]. La configuration de Docker nécessite un redémarrage de la
machine virtuelle
4. Déploiement des conteneurs applicatifs, serveur HTTP (App A) et serveur de bases de
données (App B), et un conteneur Debian (App C) grâce aux fichiers de configuration
Ansible respectifs, [Link], [Link] et [Link].
L’évaluateur se connecte en SSH à la machine virtuelle pour accéder au Client Docker CLI
grâce à la commande suivante :
4. [Link]
$ vagrant ssh
Welcome t o Ubuntu 1 8 . 0 4 . 2 LTS (GNU/ Linux 4.15.0 −46 − g e n e r i c x86_64 )
[...]
vagrant@ubuntu−b i o n i c : ~ $
L’évaluateur est connecté sur la machine virtuelle avec le compte vagrant qui appartient
au groupe docker ce qui permet d’utiliser le client Docker CLI (utilisateur client Docker CLI
défini dans le document [R5] au chapitre 1.3). Ce compte a été ajouté au fichier /etc/sudoers
pour permettre d’exécuter les tâches d’administration (utilisateur administrateur défini dans le
document [R5] au chapitre 1.3).
L’applicatif installée sur le serveur HTTP (App A) est le logiciel open-source MediaWiki 5 qui
utilise un serveur de bases de données, ici MySQL 6 (App B), pour stocker les pages dynamiques.
La configuration de MediaWiki, hors scope de l’évaluation, est présentée en annexe C.
$ ps a x j f
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
[...]
1 613 613 613 ? −1 Ssl 0 0:00 / usr / bin / containerd
1 618 618 618 ? −1 Ssl 0 0 : 0 1 / u s r / b i n / d o c k e r d −H f d : / /
Pour le déploiement d’un conteneur, par exemple le conteneur de l’image officielle de Debian
Stretch (App C) présentée en annexe B, le processus containerd-shim (/usr/bin/containerd-
shim) (figure 3) est exécuté à partir du processus containerd. Ce processus permet de « découpler »
le gestionnaire de conteneurs containerd du conteneur [1].
5. [Link]
6. [Link]
7. [Link]
8. [Link]
9. [Link]
– un système de fichiers des périphériques (/dev) de type tmpfs dans lequel Docker crée un
nombre restreint de périphériques matériels ou pseudo-périphériques (ou devices) (figure 5).
L’environnement par défaut créé par Docker contient les variables d’environnement représentées
à la figure 7.
root@5b666287be44 : /# env
HOSTNAME=5b666287be44
PWD=/
HOME=/ r o o t
TERM=xterm
SHLVL=1
PATH=/u s r / l o c a l / s b i n : / u s r / l o c a l / b i n : / u s r / s b i n : / u s r / b i n : / s b i n : / b i n
_=/u s r / b i n / env
La TOE crée, par défaut, un réseau de type « pont réseau » ou bridge, docker0, pour séparer
le réseau de l’hôte du réseau des conteneurs. Le cloisonnement de ce réseau par rapport au réseau
de l’hôte lorsque des conteneurs doivent communiquer par l’interface de l’hôte est réalisé à partir
d’un ensemble de règles iptables (figure 8).
Chain DOCKER ( 1 r e f e r e n c e s )
target p r o t opt s o u r c e destination
ACCEPT t c p −− 0 . 0 . 0 . 0 / 0 1 7 2 . 1 7 . 0 . 2 t c p dpt : 8 0 8 0
Chain DOCKER−USER ( 1 r e f e r e n c e s )
target p r o t opt s o u r c e destination
RETURN a l l −− 0 . 0 . 0 . 0 / 0 [Link]/0
Figure 8 – Règles iptables définies par Docker pour exposer le port 8080 du conteneur
Lorsqu’un conteneur est créé, la TOE le connecte, par défaut, à ce réseau (figure 9), et définit
les règles adéquates iptables pour autoriser les communications initiées par le conteneur vers
l’interface de l’hôte. Si le conteneur expose des ports, la TOE définit des règles particulières
iptables pour rediriger les communications des ports concernés de l’interface réseau de l’hôte
vers les ports définis de l’interface réseau du conteneur. Cependant, dans cette configuration, les
ports exposés d’un conteneur sont aussi accessibles à l’ensemble des conteneurs.
La TOE permet de ne pas connecter les connecteurs au réseau bridge, docker0, lors de leur
création en exécutant le daemon Docker avec l’option --bridge=none 17 (en ligne de commande ou
dans le fichier de configuration).
La TOE permet aussi de créer de nouveaux réseaux dont des réseaux de type bridge à
partir de la commande suivante : docker network create [OPTIONS] NETWORK 18 , et ainsi de
connecter un ou plusieurs conteneurs à ce réseau (option --network 19 ).
– Namespace UTS pour le hostname et le nom de domaine NIS : le conteneur possède son
propre hostname et son propre nom de domaine NIS distincts de ceux de l’hôte ou des
autres conteneurs.
Figure 10 – Isolation, par défaut, des ressources par Namespaces après la création d’un conteneur
Pour que la TOE associe, avec quelques limitations 20 , un Namespace USER ID (figure 11),
lors de la création d’un conteneur, pour isoler le ou les utilisateurs ou UID/GID d’un conteneur
des utilisateurs de l’hôte et des autres conteneurs, le daemon Docker doit être exécuté avec
l’option --userns-remap 21 (en ligne de commande ou dans le fichier de configuration). L’utilisateur
root (UID=0) du conteneur est associé par conséquent à un utilisateur non privilégié sur l’hôte
(UID=165536 sur la figure 11).
Figure 11 – Isolation des ressources par Namespaces après la création d’un conteneur
Figure 12 – Isolation des identités de CGroups et les membres de ces CGroups d’un conteneur
20. [Link]
21. [Link]
$ g e t p c a p s 1899
C a p a b i l i t i e s f o r ‘ 1 8 9 9 ’ : = cap_chown , cap_dac_override , cap_fowner , c a p _ f s e t i d ,
c a p _ k i l l , c a p _ s e t g i d , c a p _ s e t u i d , cap_setpcap , cap_net_bind_service , cap_net_raw ,
cap_sys_chroot , cap_mknod , cap_audit_write , c a p _ s e t f c a p+e i p
$ g e t p c a p s 2055
Capabilities for ‘2055 ’: =
La TOE permet de stocker et conserver des fichiers sur l’hôte même après la suppression du
conteneur grâce à l’utilisation de bind mount 28 pour monter un fichier ou un répertoire de
l’hôte dans le conteneur. Ce mécanisme permet aussi de partager un fichier ou répertoire entre
l’hôte et un ou plusieurs conteneurs ou pour partager un fichier ou un répertoire entre plusieurs
conteneurs.
La TOE permet aussi de créer un volume Docker 29 à partir de la commande suivante : docker
volume create [OPTIONS] [VOLUME] 30 , et ainsi de monter ce volume dans un ou plusieurs
conteneurs (option --volume ou --mount).
24. [Link]
25. [Link]
26. [Link]
27. [Link]
28. [Link]
29. [Link]
30. [Link]
4 Analyse de la conformité
4.1 Conformité du produit à la cible de sécurité
4.1.1 Cloisonnement
La fonction de sécurité « cloisonnement » couvre les menaces définies dans la cible de sécurité
(document [R5] au chapitre 1.3) et représentées dans le tableau 1. En effet, elle permet :
– de cloisonner le système de fichier du conteneur du système de fichier de l’hôte et aussi des
systèmes de fichier des autres conteneurs pour éviter :
– toute corruption de Docker et de sa configuration,
– toute compromission de secrets stockés sur l’hôte ou dans un autre conteneur.
– d’isoler et de limiter l’exposition des périphériques matériels ou pseudo-périphériques de
l’hôte et des autres conteneurs dont les flux standard, /dev/stdout et /dev/stderr, utilisés
pour la gestion des journaux d’évènements ;
– de cloisonner les processus de l’hôte pour éviter toute compromission des processus de l’hôte
dont les processus de Docker par un processus du conteneur,
– d’isoler l’interface réseau du conteneur de l’hôte et aussi des autres conteneurs pour toute
altération ou compromission de flux réseau.
Corruption de la configura-
Contournement de la poli-
d’évènements locaux
Altération des flux
Déni de service
des conteneurs
tique de droits
tion
M10
M1
M2
M3
M4
M5
M6
M7
M8
M9
FS1 Cloisonnement 4 4 4 4 4 4 4 4
/ 3 3 3 3
/dev 3 3
/etc/[Link]
/etc/hostname
/proc 3
/sys
réseau bridge 3 3
Par contre, elle ne permet pas de couvrir les menaces de corruption des journaux d’évènements
locaux (M9) et de corruption des journaux d’évènements des conteneurs (M10).
Corruption de la configura-
Contournement de la poli-
d’évènements locaux
Altération des flux
Déni de service
des conteneurs
tique de droits
tion
M10
M1
M2
M3
M4
M5
M6
M7
M8
M9
Isolation des
FS2 4 4 4 4 4 4 4 4 6 6
ressources
Namespace MNT 3 3 3 3
Namespace PID 3
Namespace NET 3 3 3
Namespace IPC
Namespace UTS
Namespace USER ID 3 3 3 3 3 3 3 3
/sys/fs/cgroup tmpfs 3
Tableau 2 – Couverture des menaces par la fonction de sécurité « isolation des ressources » (FS2)
Corruption de la configura-
Contournement de la poli-
d’évènements locaux
Altération des flux
Déni de service
des conteneurs
tique de droits
tion
M10
M1
M2
M3
M4
M5
M6
M7
M8
M9
Restriction des privilèges
FS3 4 4 4 4 6 6 4 6 6 6
(Capabilities par défaut)
CAP_CHOWN
CAP_DAC_OVERRIDE
CAP_FOWNER
CAP_FSETID
CAP_MKNOD
CAP_NET_RAW 3 3
CAP_SETGID
CAP_SETUID
CAP_SETFCAP
CAP_SETPCAP
CAP_NET_BIND_SERVICE 3 3
CAP_SYS_CHROOT
CAP_KILL 3
CAP_AUDIT_WRITE
Tableau 3 – Couverture des menaces par la fonction de sécurité « restriction des privilèges » (FS3)
Corruption de la configura-
Contournement de la poli-
d’évènements locaux
Altération des flux
Déni de service
des conteneurs
tique de droits
tion
M10
M1
M2
M3
M4
M5
M6
M7
M8
M9
Limitation des accès aux
FS4 4
ressources
accès d’un conteneur à la mé-
3
moire
accès d’un conteneur aux cycles
3
CPU
accès au système de fichiers
3
racine du conteneur
Tableau 4 – Couverture des menaces par la fonction de sécurité « limitation des accès aux
ressources » (FS4)
CVE ID Description
CVE-2016-8867 Incorrect application of ambient capabilities
CVE-2014-8178 Attacker controlled layer IDs lead to local graph content poisoning
CVE-2014-8179 Manifest validation and parsing logic errors allow pull-by-digest validation
bypass
CVE-2015-3629 Symlink traversal on container respawn allows local privilege escalation
CVE-2015-3627 Insecure opening of file-descriptor 1 leading to privilege escalation
CVE-2015-3630 Read/write proc paths allow host modification & information disclosure
CVE-2015-3631 Volume mounts allow LSM profile escalation
Une recherche par produit sur le site CVE Details 34 fournit une liste 35 de vulnérabilités plus
importantes représentées dans le tableau 6. L’affichage en distributions, par année et par type de
vulnérabilités, est représentée sur la figure 15.
Dans le cadre de cette évaluation, aucune de ces vulnérabilités n’aurait permis à notre modèle
d’attaquant de compromettre la TOE.
CVE ID Description
CVE-2018-15514 HandleRequestAsync in Docker for Windows before 18.06.0-ce-rc3-win68
(edge) and before 18.06.0-ce-win72 (stable) deserialized requests over the
named pipe without verifying the validity of the deserialized .NET objects.
This would allow a malicious user in the "docker-users" group (who may
not otherwise have administrator access) to escalate to administrator
privileges.
CVE-2017-14992 Lack of content verification in Docker-CE (Also known as Moby) versions
1.12.6-0, 1.10.3, 17.03.0, 17.03.1, 17.03.2, 17.06.0, 17.06.1, 17.06.2, 17.09.0,
and earlier allows a remote attacker to cause a Denial of Service via a
crafted image layer payload, aka gzip bombing.
CVE-2017-7297 Rancher Labs rancher server 1.2.0+ is vulnerable to authenticated
users disabling access control via an API call. This is fixed in versions
rancher/server :v1.2.4, rancher/server :v1.3.5, rancher/server :v1.4.3, and
rancher/server :v1.5.3.
CVE-2016-9962 RunC allowed additional container processes via ’runc exec’ to be ptraced
by the pid 1 of the container. This allows the main processes of the
container, if running as root, to gain access to file-descriptors of these new
processes during the initialization and can lead to container escapes or
modification of runC state before the process is fully placed inside the
container.
CVE-2016-8867 Docker Engine 1.12.2 enabled ambient capabilities with misconfigured ca-
pability policies. This allowed malicious images to bypass user permissions
to access files within the container filesystem or mounted volumes.
32. [Link]
33. consulté le 26 mars 2019
34. [Link]
35. consultée le 26 mars 2019
CVE ID Description
CVE-2016-6595 ** DISPUTED ** The SwarmKit toolkit 1.12.0 for Docker allows remote
authenticated users to cause a denial of service (prevention of cluster joins)
via a long sequence of join and quit actions. NOTE : the vendor disputes
this issue, stating that this sequence is not "removing the state that is
left by old nodes. At some point the manager obviously stops being able
to accept new nodes, since it runs out of memory. Given that both for
Docker swarm and for Docker Swarmkit nodes are *required* to provide a
secret token (it’s actually the only mode of operation), this means that
no adversary can simply join nodes and exhaust manager resources. We
can’t do anything about a manager running out of memory and not being
able to add new legitimate nodes to the system. This is merely a resource
provisioning issue, and definitely not a CVE worthy vulnerability."
CVE-2016-3697 libcontainer/user/[Link] in runC before 0.1.0, as used in Docker before
1.11.2, improperly treats a numeric UID as a potential username, which
allows local users to gain privileges via a numeric username in the password
file in a container.
CVE-2015-3631 Docker Engine before 1.6.1 allows local users to set arbitrary Linux Security
Modules (LSM) and docker_t policies via an image that allows volumes
to override files in /proc.
CVE-2015-3630 Docker Engine before 1.6.1 uses weak permissions for (1) /proc/asound,
(2) /proc/timer_stats, (3) /proc/latency_stats, and (4) /proc/fs, which
allows local users to modify the host, obtain sensitive information, and
perform protocol downgrade attacks via a crafted image.
CVE-2015-3627 Libcontainer and Docker Engine before 1.6.1 opens the file-descriptor
passed to the pid-1 process before performing the chroot, which allows
local users to gain privileges via a symlink attack in an image.
CVE-2014-9358 Docker before 1.3.3 does not properly validate image IDs, which allows
remote attackers to conduct path traversal attacks and spoof repositories
via a crafted image in a (1) "docker load" operation or (2) "registry
communications."
CVE-2014-9357 Docker 1.3.2 allows remote attackers to execute arbitrary code with root
privileges via a crafted (1) image or (2) build in a Dockerfile in an LZMA
(.xz) archive, related to the chroot for archive extraction.
CVE-2014-6408 Docker 1.3.0 through 1.3.1 allows remote attackers to modify the default
run profile of image containers and possibly bypass the container by
applying unspecified security options to an image.
CVE-2014-6407 Docker before 1.3.2 allows remote attackers to write to arbitrary files and
execute arbitrary code via a (1) symlink or (2) hard link attack in an
image archive in a (a) pull or (b) load operation.
CVE-2014-5282 Docker before 1.3 does not properly validate image IDs, which allows
remote attackers to redirect to another image through the loading of
untrusted images via ’docker load’.
CVE-2014-5277 Docker before 1.3.1 and docker-py before 0.5.3 fall back to HTTP when the
HTTPS connection to the registry fails, which allows man-in-the-middle
attackers to conduct downgrade attacks and obtain authentication and
image data by leveraging a network position between the client and the
registry to block HTTPS traffic.
CVE-2014-3499 Docker 1.0.0 uses world-readable and world-writable permissions on the
management socket, which allows local users to gain privileges via unspec-
ified vectors.
CVE-2014-0047 Docker before 1.5 allows local users to have unspecified impact via vectors
involving unsafe /tmp usage.
Parmi ces composants, la bibliothèque C GNU standard (ou glibc) concentre un grand nombre
de vulnérabilités comme le montrent les distributions 37 , par année et par type de vulnérabilités,
représentées sur la figure 17.
37. consultées le 26 mars 2019
$ v a g r a n t up
[...]
TASK [ Execute / u s r / b i n / docker −runc ] ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗
changed : [ d e f a u l t ]
TASK [ debug ] ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗
ok : [ d e f a u l t ] => {
" ou tp ut . s t d o u t _ l i n e s " : [
"" ,
" ∗∗THE ALL NEW AND IMPROVED RUNC∗∗ " ,
"" ,
" \ t [ + ] Your backdoor h e r e −>"
]
}
41. [Link]
R1- Une gestion centralisée des journaux d’évènements issus des applications « con-
teneurisées », distincte de Docker, peut être mise en œuvre.
R2 Le daemon Docker doit être configuré pour démarrer un conteneur sans le connecter,
par défaut, au réseau bridge, docker0, avec l’option --bridge=none (en ligne de
commande ou dans le fichier de configuration). Si le conteneur doit être connecté à
l’interface réseau de l’hôte ou à un ou plusieurs autres connecteurs, un réseau doit
être créé à partir de la commande docker network create [OPTIONS] NETWORK et
les interfaces réseau du ou des conteneurs devront alors être connectées à ce réseau
avec l’option --network.
R3 Le daemon Docker doit être configuré pour démarrer un conteneur avec un Namespace
USER ID distinct de l’hôte et des autres conteneurs avec l’option --userns-remap (en
ligne de commande ou dans le fichier de configuration).
R3- Un conteneur peut être démarré en partageant le Namespace USER ID de l’hôte avec
l’option --userns=host quand le daemon Docker est configuré pour démarrer les
conteneurs avec un Namespace USER ID distinct de l’hôte.
R4 Chaque conteneur doit être démarré sans aucune capability avec l’option --cap-
drop=ALL.
En effet, les capabilities par défaut de Docker ne sont pas nécessaires [4] en production :
– CAP_CHOWN : cette capability n’est pas nécessaire en production ;
– CAP_DAC_OVERRIDE : cette capability n’est pas nécessaire en production ;
– CAP_FOWNER : cette capability n’est pas nécessaire en production, le cas échéant
l’action ou les actions nécessitant cette capability doivent être réalisées lors de la con-
struction du conteneur dans le Dockerfile ;
– CAP_FSETID : cette capability n’est pas nécessaire en production ;
– CAP_MKNOD : cette capability n’est pas nécessaire en production, le cas échéant la
création du périphérique doit être réalisée lors du démarrage du conteneur avec l’option
--device ;
– CAP_NET_RAW : cette capability n’est pas nécessaire en production ;
42. [Link]
43. [Link]
44. [Link]
stretch/apache/Dockerfile
R4- Un conteneur peut être démarré avec un nombre très limité de capabilities avec
les options --cap-drop=ALL et --cap-add={"capability A"}.
R5 Chaque conteneur doit être démarré avec une limite maximale d’utilisation de la
mémoire de l’hôte avec l’option --memory et une limite maximale d’utilisation de la
mémoire SWAP de l’hôte avec l’option --memory-swap 46 .
R6 Chaque conteneur doit être démarré avec une limite maximale d’utilisation du CPU
de l’hôte avec l’option --cpus ou avec les options --cpu-period et --cpu-quota.
R7 Chaque conteneur doit être démarré avec leur système de fichiers racine ou root
filesystem en lecture seule avec l’option --read-only. Après avoir identifié les réper-
toires contenant des données non persistantes ou temporaires, ces répertoires doivent
être montés à l’aide d’un montage bind tmpfs 47 ou avec l’option --mount type=tmpfs.
R7- Un conteneur peut être démarré avec une limite maximale d’utilisation de l’espace
disque de l’hôte pour leur système de fichiers racine ou root filesystem en lecture-
écriture avec l’option --storage-opt.
45. [Link]
46. [Link]
47. [Link] avec l’option --tmpfs
R7-- Un conteneur peut être démarré avec son système de fichiers racine ou root
filesystem en lecture-écriture dès lors que la zone de stockage local de Docker,
qui, par défaut /var/lib/docker/ sur Linux, est une partition dédiée et distincte des
partitions de l’hôte. Dans ce cas, la menace d’un déni de service d’un conteneur vis à
vis d’un autre conteneur ou sur le service Docker est à considérer.
R8 Les répertoires contenant des données persistantes ou partagées avec l’hôte ou avec
d’autres conteneurs doivent être montés à l’aide de :
– un montage bind mount 48 avec une limitation de l’espace disque utilisé grâce
à l’option --mount type=bind, o=size,
– un montage bind volume 49 d’une partition dédiée et distincte des partitions
utilisées par l’hôte ou d’un volume Docker avec une limitation définie de l’espace
disque grâce à l’option --mount type=volume.
Docker, Inc. fournit un conteneur Docker 51 qui réalise une analyse de sécurité de l’environ-
nement Docker d’un hôte au regard des ces recommandations.
L’analyse effectuée avec le conteneur Docker sur l’architecture trois tiers définie à la section 2
donne le résultat de la figure 19.
51. [Link]
[ INFO ] Checks : 16
[ INFO ] S c o r e : 15
7 Synthèse
7.1 Installation du produit
Docker Community Edition (CE)est constitué des services ou processus suivants :
– dockerd qui est exécuté avec l’utilisateur root (UID=0 ). Ce processus est fortement exposé,
car il permet d’administrer et configurer la TOE à partir de l’interface REST (REST API),
– containerd et containerd-shim qui permet à containerd d’interagir avec le conteneur qui
sont, tous les deux, exécutés avec l’utilisateur root (UID=0 ). Ces processus sont directement
ou indirectement exposés au conteneur. La CVE-2019-5736 a montré qu’une vulnérabilité
dans l’un de ces processus permet à un attaquant ayant compromis un conteneur de
compromettre l’hôte.
L’analyse de sécurité de ces processus est hors scope de l’évaluation mais un durcissement du
système et des services 52 Docker doit être réalisé pour réduire la surface d’attaque
de Docker et les risques de compromission de l’hôte.
7.3 Conformité
La section 4 montre que la couverture des menaces par les fonctions de sécurité définies
du document [R5] au chapitre 1.3 n’est pas conforme. Une nouvelle version, document [R6] au
chapitre 1.3, a été rédigée pour corriger les non-conformités.
7.4 Vulnérabilités
Docker Community Edition (CE) présente peu de vulnérabilités connues, et ces vulnérabilités
concernent, pour la plupart, la création du conteneur à partir d’une image malveillante. Par
contre, du fait que la sécurité de Docker Community Edition (CE) repose principalement sur les
mécanismes de sécurité du noyau et sur des composants externes dont la bibliothèque C GNU
standard (ou glibc) qui présente un grand nombre de vulnérabilités, une vulnérabilité d’un de
ces mécanismes ou d’un des ces composants peut être exploitée sur Docker Community Edition
(CE) , par exemple, la récente CVE-2019-5736 de la bibliothèque containerd.
56. [Link]
57. [Link]
58. [Link]
APPA_NAME = "AppA"
APPB_NAME = "AppB"
APPC_NAME = "AppC"
GUEST_PORT = " 80 "
HOST_PORT = " 8080 "
MYSQL_DATABASE = " my_wiki "
MYSQL_USER = " wikiuser "
MYSQL_PASSWORD = " example "
NETWORK1_NAME = " docker1 "
NETWORK2_NAME = " docker2 "
# I n s t a l l p y th o n f o r a n s i b l e
c o n f i g . vm . p r o v i s i o n " s h e l l " , i n l i n e : <<−SHELL
t e s t −e / u s r / b i n / python | | ( apt−g e t −qqy update && apt−g e t i n s t a l l −qqy python
−minimal > / dev / n u l l 2>&1)
SHELL
c o n f i g . vm . p r o v i s i o n : r e l o a d
# MediaWiki c o n t a i n e r (AppA)
c o n f i g . vm . p r o v i s i o n " a n s i b l e " do | a n s i b l e |
a n s i b l e . compatibility_mode = " 2 . 0 "
a n s i b l e . playbook = "AppA . yml "
a n s i b l e . extra_vars = {
container_name : APPB_NAME,
network1_name : NETWORK1_NAME,
network2_name : NETWORK2_NAME,
med iawiki _port : GUEST_PORT,
mysql_name : APPA_NAME,
}
end
# Debian c o n t a i n e r (AppC)
c o n f i g . vm . p r o v i s i o n " a n s i b l e " do | a n s i b l e |
− hosts : a l l
become : y e s
tasks :
# I n s t a l l Docker CE u s i n g t h e r e p o s i t o r y
− name : Add Docker ’ s o f f i c i a l GPG key
apt_key :
u r l : h t t p s : / / download . d o c k e r . com/ l i n u x / ubuntu / gpg
state : present
− name : S e t up t h e s t a b l e r e p o s i t o r y
apt_repository :
r e p o : " deb [ a r c h=amd64 ] h t t p s : / / download . d o c k e r . com/ l i n u x / ubuntu b i o n i c
stable "
state : present
filename : docker
− name : R e s t a r t s e r v i c e d o c k e r
service :
name : d o c k e r
state : restarted
− hosts : a l l
become : y e s
vars :
apache2_uid : 10
apache2_gid : 10
apache_port : 8080
cpu_period : " 100000 "
cpu_quota : " 40000 "
memory : " 300M"
memory_swap : " 300M"
tasks :
− name : C r e a t e a network
docker_network :
name : " {{ network1_name }} "
− name : C r e a t e D o c k e r f i l e f o r AppA
blockinfile :
path : /home/ v a g r a n t / D o c k e r f i l e . AppA
c r e a t e : yes
owner : v a g r a n t
group : v a g r a n t
block : |
FROM m e d i a w i k i : 1 . 3 2 . 0
RUN s e d − i \
−e ’ s / ^ \ ( : $ {APACHE_PID_FILE:=\) . ∗ \ ( \ / apache2 . p i d \ ) /\1\/tmp\2/ ’ \
−e ’ s / ^ \ ( : $ {APACHE_RUN_DIR:=\) . ∗ / \ 1 \ / tmp}/ ’ \
−e ’ s / ^ \ ( : $ {APACHE_LOCK_DIR:=\) . ∗ / \ 1 \ / tmp}/ ’ \
−e ’ s / ^ \ ( : $ {APACHE_LOG_DIR:=\) . ∗ / \ 1 \ / tmp}/ ’ \
/ e t c / apache2 / e n v v a r s
RUN s e d − i \
−e ’ s / ^ \ ( L i s t e n \ ) . ∗ / \ 1 { { apache_port }}/ ’ \
/ e t c / apache2 / p o r t s . c o n f
RUN s e d − i \
−e ’ s /^\(< V i r t u a l H o s t ∗ : \ ) . ∗ \ ( > \ ) /\1{{ apache_port }}\2/ ’ \
/ e t c / apache2 / s i t e s −e n a b l e d /000− d e f a u l t . c o n f
EXPOSE {{ apache_port }}
# d o c k e r n e t w o r k c o n n e c t d o c k e r 2 AppA
− name : Add/Append AppA c o n t a i n e r t o d o c k e r 2 network
docker_network :
name : " {{ network2_name }} "
connected :
− " {{ mysql_name }} "
appends : y e s
− hosts : a l l
become : y e s
vars :
cpu_period : " 100000 "
cpu_quota : " 40000 "
memory : " 1G"
memory_swap : " 1G"
m y s q l _ d a t a b a s e _ s i z e : " 500M"
mysql_uid : 20
mysql_gid : 20
mysql_random_root_password : " y e s "
tasks :
− name : C r e a t e a network
docker_network :
name : " {{ network2_name }} "
group : mysql
create_home : no
− name : C r e a t e D o c k e r f i l e f o r AppB
blockinfile :
path : /home/ v a g r a n t / D o c k e r f i l e . AppB
owner : v a g r a n t
group : v a g r a n t
c r e a t e : yes
block : |
FROM mysql : 8 . 0 . 1 4
RUN s e d − i \
−e ’ s / ^ \ ( pid− f i l e .∗=\) . ∗ \ ( mysqld . p i d \ ) /\1 \/tmp\/\2/ ’ \
−e ’ s / ^ \ ( s o c k e t .∗=\) . ∗ \ ( mysqld . s o c k \ ) /\1 \/tmp\/\2/ ’ \
/ e t c / mysql /my . c n f
− hosts : a l l
become : y e s
vars :
cpu_period : " 100000 "
cpu_quota : " 40000 "
memory : " 300M"
memory_swap : " 300M"
tasks :
# Run AppC ( Debian S t r e t c h ) i n c o n t a i n e r
# d o c k e r run −−name AppC −−cap−drop=ALL −−read−o n l y −−t m p f s /tmp \
# −−cpu−p e r i o d =100000 −−cpu−q u o t a =40000 \
# −−memory="300M" −−memory−swap ="300M" \
# −−d e t a c h − i t ppc
− name : Run AppC c o n t a i n e r
docker_container :
name : " {{ container_name }} "
image : d e b i a n : s t r e t c h −s l i m
tty : yes
cpu_period : " {{ cpu_period }} "
cpu_quota : " {{ cpu_quota }} "
memory : " {{ memory }} "
memory_swap : " {{ memory_swap }} "
cap_drop :
− all
read_only : y e s
tmpfs :
− " /tmp "
59. [Link]
60. [Link]
61. [Link]
Annexe C MediaWiki
C.1 Introduction
MediaWiki 62 est un moteur de wiki pour le Web, écrit en PHP, qui peut aussi bien fonctionner
avec le système de gestion de base de données MySQL que PostgreSQL.
L’instance est accessible depuis l’hôte sans l’IP du conteneur à l’adresse [Link]
ou [Link] dans un navigateur.
C.3 Configuration
À l’issue de l’instanciation de l’image, il faut configurer l’application pour qu’elle puisse se
connecter à la base de données (adresse IP, mot de passe, nom de la base de données, etc.) et
pour définir les nom et mot de passe de l’administrateur de l’application.
Lors de la première connexion à l’application et en l’absence de fichier de configuration
([Link]), la page d’accueil représentée à la figure 20 est affichée.
Après la page de paramètrage de la base de données qui nécessite aucune modification particulière,
la page de configuration de l’application représenteé à la figure 22 est affichée. Les champs suivants
correspondent :
– Nom du wiki : le nom du wiki qui apparaîtra dans la barre de titre du navigateur et en
divers autres endroits ;
– Votre nom d’utilisateur : le nom du compte administrateur de l’application MediaWiki ;
– Mot de passe : le mot de passe du compte administrateur de l’application MediaWiki à
saisir une seconde fois Saisir à nouveau le mot de passe.
Cocher la case J’en ai assez, installer simplement le wiki. pour ne pas poursuivre la configuration
plus que nécessaire.
Pour que l’application MediaWiki prenne en compte le fichier de configuration généré, la ligne
suivante du fichier de configuration Ansible [Link] doit être décommentée :
tmpfs :
− " /tmp "
# uncomment t h e f o l l o w i n g l i n e s and r e s t a r t t h e m e d i a w i k i s e r v i c e
volumes :
− " / v a g r a n t /AppA/ L o c a l S e t t i n g s . php : / v a r /www/ html / L o c a l S e t t i n g s . php "
$ vagrant p r o v i s i o n
À l’issue du conteneur, une nouvelle page d’accueil représentée à la figure 24 est affichée.
# I n s t a l l p y th o n f o r a n s i b l e
c o n f i g . vm . p r o v i s i o n " s h e l l " , i n l i n e : <<−SHELL
t e s t −e / u s r / b i n / python | | ( apt−g e t −qqy update && apt−g e t i n s t a l l −qqy python
−minimal > / dev / n u l l 2>&1)
SHELL
# h t t p s : / / g i t h u b . com/ t w i s t l o c k /RunC−CVE−2019−5736
c o n f i g . vm . p r o v i s i o n " a n s i b l e " do | a n s i b l e |
a n s i b l e . compatibility_mode = " 2 . 0 "
a n s i b l e . playbook = "CVE−2019 −5736. yml "
end
end
− hosts : a l l
become : y e s
tasks :
− name : Clone RunC−CVE−2019−5736 ( T w i s t l o c k )
git :
r e p o : h t t p s : / / g i t h u b . com/ t w i s t l o c k /RunC−CVE−2019 −5736. g i t
d e s t : /home/ v a g r a n t /RunC−CVE−2019−5736
Références
[1] Michael Crosby. Building a container supervisor, 2016. [Link]
crosbymichael/dockercon-2016/blob/master/Creating%[Link].
[2] Center for Internet Security. Cis docker community edition benchmarki v1.1.0, June 2017.
[Link]
[3] Alexander Holbreich. Docker components explained, Avril 2018. [Link]
[Link]/docker-components-explained/.
[4] Dan Walsh. Secure your containers with this one weird trick, October 2016. [Link]
[Link]/2016/10/17/secure-your-containers-with-this-one-weird-trick/.