
Los procesos en un contenedor Docker no necesitan ejecutarse como root. Es más seguro ejecutar sus aplicaciones como un usuario no root que especifica como parte de su Dockerfile o cuando usa docker run
. Esto minimiza el riesgo al presentar una pequeña superficie de ataque a cualquier amenaza en el contenedor.
En este artículo, aprenderá los peligros de ejecutar aplicaciones en contenedores como root. También verá cómo crear un usuario no root y configurar el espacio de nombres en situaciones en las que esto no es posible.
¿Por qué es peligroso ejecutar como root?
CONTENIDOS DE LA PAGINA
Los contenedores se ejecutan como raíz de forma predeterminada. El demonio Docker se ejecuta como root en su host y los contenedores en ejecución también serán root.
Si bien puede parecer que la raíz dentro del contenedor es un usuario independiente, en realidad es lo mismo que la cuenta raíz en su host. La separación solo la proporcionan los mecanismos de aislamiento de contenedores de Docker. No hay un límite físico fuerte; su contenedor es otro proceso ejecutado por el usuario root en el kernel de su host. Esto significa que una vulnerabilidad en la aplicación, el tiempo de ejecución de Docker o el kernel de Linux podría permitir a los atacantes salir del contenedor y realizar operaciones con privilegios de root en la computadora.
Hay algunas protecciones integradas que reducen el riesgo de que esto suceda. La raíz dentro del contenedor no tiene privilegios y tiene capacidades limitadas. Esto evita que el contenedor use comandos de administración del sistema a menos que agregue funciones manualmente o use el modo privilegiado al iniciar los contenedores.
A pesar de esta mitigación, permitir que las aplicaciones se ejecuten como root sigue siendo un peligro. Así como limitaría el uso de root en un entorno tradicional, no es aconsejable usarlo innecesariamente dentro de sus contenedores. Está proporcionando un entorno privilegiado que brinda a los atacantes un mayor punto de apoyo en caso de que se produzca una infracción.
Ejecución de aplicaciones en contenedores como usuario no root
Se recomienda que las aplicaciones en contenedores se ejecuten como un usuario normal. La mayoría del software no requiere acceso de raíz, por lo que la modificación del usuario proporciona un nivel inmediato de defensa contra la ruptura de contenedores.
Debe crear una nueva cuenta de usuario como uno de los pasos finales en su Dockerfile. Puedes lograr esto con el USER
instrucción:
FROM base-image:latest RUN apt install demo-package USER demo-user:demo-group ENTRYPOINT ["demo-binary"]
Los contenedores lanzados desde esta imagen se ejecutarán como demo-user
. El usuario será miembro de la demo-group
grupo. Puede omitir el nombre del grupo si el usuario no necesita estar en un grupo:
USER demo-user
Puede especificar una ID de usuario (UID) y una ID de grupo (GID) en lugar de nombres:
USER 950:950
La asignación de un UID y GID conocido suele ser la forma más segura de proceder. Evita que el usuario del contenedor se asigne a una cuenta de host con privilegios excesivos.
USER
a menudo se especifica como la penúltima etapa en un Dockerfile. Esto significa que aún puede realizar operaciones que requieren root antes en la creación de la imagen. los apt install
la declaración en el ejemplo anterior tiene una necesidad legítima de root. Si el USER
la educación se colocó por encima de ella, apt
correría como demo-user
que carecería de los permisos necesarios. Dado que las instrucciones de Dockerfile solo se aplican a las compilaciones de imágenes, no a los contenedores en ejecución, puede dejar que el usuario edite hasta más adelante en el Dockerfile.
El cambio de usuario realizado por el contenedor puede requerir la actualización de permisos en los archivos y carpetas a los que acceden. Establezca la propiedad en todas las rutas que usará su aplicación:
COPY initial-config.yaml /data/config.yaml USER demo-user:demo-group RUN chown demo-user:demo-group /data
En este ejemplo el /data
el directorio debe ser propiedad de demo-user
para que la aplicación pueda realizar cambios en su archivo de configuración. El anterior COPY
la instrucción habrá copiado el archivo como root. Un atajo está disponible usando el --chown
bandera con copy
:
COPY --chown=demo-user:demo-group initial-config.yaml /data/config.yaml
Cambio de usuario al iniciar un contenedor
Si bien puede cambiar fácilmente el usuario en sus Dockerfiles, muchas aplicaciones de terceros aún se ejecutan como root. Puede reducir el riesgo asociado con el uso de estos configurando el --user
señal cada vez que llamas docker run
. Esto anula el conjunto de usuarios en el Dockerfile de la imagen.
$ 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
los --user
flag ejecuta el proceso del contenedor como el usuario especificado. Es menos seguro que el Dockerfile USER
instrucciones porque tienes que aplicarlo individualmente a cada docker run
dominio. Una mejor opción para las imágenes de uso regular es crear su propia imagen derivada que puede configurar una nueva cuenta de usuario:
FROM image-that-runs-as-root:latest USER demo-user
$ docker build . -t image-that-now-runs-as-non-root:latest
Cambiar el usuario de una imagen de terceros puede causar problemas: si el contenedor planea ejecutarse como root o necesita acceder a las rutas del sistema de archivos propiedad del root, se mostrarán errores mientras se usa la aplicación. Puede intentar cambiar manualmente los permisos en las rutas problemáticas. Como alternativa, verifique si el proveedor tiene un método compatible para ejecutar la aplicación con una cuenta de usuario sin privilegios.
Gestión de aplicaciones que deben ejecutarse como root
El espacio de nombres de usuario es una técnica para administrar aplicaciones que requieren algunos privilegios de raíz. Le permite asignar la raíz dentro de un contenedor a un usuario no raíz en su host. La raíz simulada dentro del contenedor tiene los privilegios necesarios, pero una interrupción no proporcionará acceso de raíz al host.
La reasignación de espacios de nombres se habilita agregando un userns-remap
campo tuyo /etc/docker/daemon.json
expediente:
{ "userns-remap": "default" }
Usando default
como un valor para userns-remap
indica a Docker que cree automáticamente un nuevo usuario llamado en su host dockremap
. La raíz dentro de los contenedores se mapeará de nuevo a dockremap
en su anfitrión. En su lugar, puede especificar un usuario y un grupo existentes mediante una combinación de UID/GID o nombre de usuario/nombre de grupo:
{ "userns-remap": "demo-user" }
Reinicie el demonio de Docker después de aplicar el cambio:
$ sudo service docker restart
Si estás usando nsuser-remap: default
la dockremap
el usuario ahora debería existir en su host:
$ id dockremap uid=140(dockremap) gid=119(dockremap) groups=119(dockremap)
El usuario también debe aparecer en el archivo. /etc/subuid
Y /etc/subgid
archivos de ID subordinados:
$ dockremap:231500:65535
Al usuario se le ha asignado un rango de 65 535 ID subordinados a partir de 231500. Dentro del espacio de nombres de usuario, ID 231500
está asignado a , convirtiéndolo en el usuario raíz en sus contenedores. Al ser un UID de número alto, 231500 no tiene privilegios en el host, por lo que los ataques de ruptura de contenedores no podrán causar tanto daño.
Todos los contenedores que inicie se ejecutarán utilizando el espacio de nombre de usuario reasignado a menos que decida darse por vencido. docker run --userns=host
. El mecanismo funciona mediante la creación de directorios con espacio de nombres dentro /var/lib/docker
que son propiedad del UID y el GID subordinado del usuario con espacio de nombres:
$ sudo ls -l /var/lib/docker/231500.231500 total 14 drwx------ 5 231500 231500 13 Jul 22 19:00 aufs drwx------ 3 231500 231500 13 Jul 22 19:00 containers ...
El espacio de nombre de usuario es una forma eficaz de aumentar el aislamiento del contenedor, evitar interrupciones y preservar la compatibilidad con las aplicaciones que requieren privilegios de raíz. Sin embargo, existen algunas ventajas y desventajas: la función funciona mejor en una nueva instancia de Docker, los volúmenes montados en el host deben tener permisos ajustados y algunos controladores de almacenamiento externo no admiten el mapeo de usuarios en absoluto. Debe revisar la documentación antes de adoptar esta opción.
Resumen
Ejecutar aplicaciones en contenedores como raíz es un riesgo de seguridad. Si bien es fácil pasarlo por alto, el aislamiento proporcionado por los contenedores no es lo suficientemente sólido como para separar por completo a los usuarios del kernel de los usuarios de los contenedores. La raíz en el contenedor es la misma que la raíz en su host, por lo que un compromiso exitoso podría proporcionar el control de su computadora.
Como autor de una imagen, debe incluir la USER
instrucciones en el Dockerfile para que la aplicación se ejecute sin root. Los usuarios de imágenes pueden sobrescribirlo con docker run --user
para asignar un UID y GID específico. Esto ayuda a mitigar los casos en los que la imagen normalmente usa la raíz.
Puede fortalecer aún más la seguridad eliminando todas las funciones del contenedor usando --cap-drop=ALL
luego lista blanca los necesarios con --cap-add
banderas La combinación de estas técnicas ejecutará su aplicación como un usuario no root con el conjunto mínimo de privilegios que necesita, mejorando su postura de seguridad.