Cuando ejecuto un contenedor como un usuario normal, puedo mapear y modificar directorios propiedad de root en mi sistema de archivos host. Esto parece ser un gran agujero de seguridad. Por ejemplo puedo hacer lo siguiente:
$ docker run -it --rm -v /bin:/tmp/a debian root@14da9657acc7:/# cd /tmp/a root@f2547c755c14:/tmp/a# mv df df.orig root@f2547c755c14:/tmp/a# cp ls df root@f2547c755c14:/tmp/a# exit Ahora mi sistema de archivos host ejecutará el comando ls cuando se escriba df (ejemplo en su mayoría inofensivo). No puedo creer que este sea el comportamiento deseado, pero está sucediendo en mi sistema (debian stretch). El comando docker tiene permisos normales (755, no setuid).
¿Qué me estoy perdiendo?
Quizá sea bueno aclarar un poco más. En este momento no estoy interesado en lo que hace o puede hacer el contenedor en sí mismo, ni me preocupa el acceso de root dentro del contenedor.
Más bien, me doy cuenta de que cualquier persona en mi sistema que pueda ejecutar un contenedor docker puede usarlo para obtener acceso de root a mi sistema host y leer/escribir como root lo que quiera: otorgar efectivamente a todos los usuarios acceso de root. Eso obviamente no es lo que quiero. ¿Cómo prevenir esto?
Hay muchas funciones de seguridad de Docker disponibles para ayudar con los problemas de seguridad de Docker. El específico que lo ayudará es User Namespaces.
Básicamente, debe habilitar los espacios de nombres de usuario en la máquina host con el demonio Docker detenido de antemano:
dockerd --userns-remap=default &Tenga en cuenta que esto prohibirá que el contenedor se ejecute en modo privilegiado (algo bueno desde el punto de vista de la seguridad) y reiniciará el demonio Docker (debe detenerse antes de ejecutar este comando). Cuando ingresa al contenedor Docker, puede restringirlo al usuario actual sin privilegios:
docker run -it --rm -v /bin:/tmp/a --user UID:GID debianDe todos modos, intente ingresar al contenedor Docker después con su comando predeterminado de
docker run -it --rm -v /bin:/tmp/a debian Si intenta manipular el sistema de archivos del host que se asignó a un volumen de Docker (en este caso /bin ) donde los archivos y directorios son propiedad de root, recibirá un error de Permission denied . Esto demuestra que los espacios de nombres de usuario proporcionan la funcionalidad de seguridad que está buscando.
Recomiendo pasar por el laboratorio de Docker sobre esta función de seguridad en https://github.com/docker/labs/tree/master/security/userns . Realicé todos los laboratorios y abrí problemas y relaciones públicas allí para garantizar la integridad de los laboratorios allí y puedo responder por ellos.
El acceso para ejecutar los comandos de Docker en un host es el acceso a la raíz en ese host. Este es el diseño de la herramienta ya que la funcionalidad para montar sistemas de archivos y aislar una aplicación requiere capacidades de root en Linux. La vulnerabilidad de seguridad aquí es cualquier administrador de sistemas que otorgue acceso a los usuarios para ejecutar comandos de Docker en los que de otro modo no confiarían con acceso de root en ese host. Por lo tanto, la adición de usuarios al grupo docker debe hacerse con cuidado.
Todavía veo a Docker como una mejora de seguridad cuando se usa correctamente, ya que las aplicaciones que se ejecutan dentro de un contenedor están restringidas de lo que pueden hacer al host. La capacidad de causar daño se brinda con opciones explícitas para ejecutar el contenedor, como montar el sistema de archivos raíz como un volumen rw, acceso directo a dispositivos o agregar capacidades a la raíz que permiten escapar del espacio de nombres. Salvo la creación explícita de esos agujeros de seguridad, una aplicación que se ejecuta dentro de un contenedor tiene mucho menos acceso que si se ejecutara fuera del contenedor.
Si aún desea intentar bloquear a los usuarios con acceso a la ventana acoplable, existen algunas funciones de seguridad adicionales. El espacio de nombres de usuario es uno de los que evita que la raíz dentro del contenedor tenga acceso de raíz en el host. También hay interbloqueo que le permite limitar los comandos disponibles por usuario.
Le falta que los contenedores se ejecuten internamente como uid 0 de forma predeterminada. Así que esto es lo esperado. Si desea restringir más el permiso dentro del contenedor, constrúyalo con una declaración de USER en Dockerfile. Esto configurará el nombre del usuario en tiempo de ejecución, en lugar de ejecutarse como root.
Tenga en cuenta que el uid de este usuario no es necesariamente predecible, ya que se asigna dentro de la imagen que crea, y no necesariamente se asignará a nada en el sistema externo. Sin embargo, el punto es que no será root.
Consulte la referencia de Dockerfile para obtener más información.