{"id":101162,"date":"2022-08-17T09:50:15","date_gmt":"2022-08-17T09:50:15","guid":{"rendered":"https:\/\/magazineoffice.com\/por-que-los-procesos-en-contenedores-docker-no-deberian-ejecutarse-como-raiz\/"},"modified":"2022-08-17T09:50:16","modified_gmt":"2022-08-17T09:50:16","slug":"por-que-los-procesos-en-contenedores-docker-no-deberian-ejecutarse-como-raiz","status":"publish","type":"post","link":"https:\/\/magazineoffice.com\/por-que-los-procesos-en-contenedores-docker-no-deberian-ejecutarse-como-raiz\/","title":{"rendered":"Por qu\u00e9 los procesos en contenedores Docker no deber\u00edan ejecutarse como ra\u00edz"},"content":{"rendered":"


\n<\/p>\n

\n

Los procesos en un contenedor Docker no deben ejecutarse como root. Es m\u00e1s seguro ejecutar sus aplicaciones como un usuario no root que especifica como parte de su Dockerfile o cuando usa docker run<\/code>. Esto minimiza el riesgo al presentar una superficie de ataque reducida para cualquier amenaza en su contenedor.<\/p>\n

En este art\u00edculo, aprender\u00e1 sobre los peligros de ejecutar aplicaciones en contenedores como root. Tambi\u00e9n ver\u00e1 c\u00f3mo crear un usuario no ra\u00edz y configurar el espacio de nombres en situaciones en las que esto no es posible.<\/p>\n

\u00bfPor qu\u00e9 es peligroso ejecutar como ra\u00edz?<\/h2>\n

Los contenedores se ejecutan como ra\u00edz de forma predeterminada. El demonio Docker se ejecuta como root en su host y los contenedores en ejecuci\u00f3n tambi\u00e9n ser\u00e1n root.<\/p>\n

Aunque puede parecer que la ra\u00edz dentro del contenedor es un usuario independiente, en realidad es lo mismo que la cuenta ra\u00edz en su host. La separaci\u00f3n solo la proporcionan los mecanismos de aislamiento de contenedores de Docker. No hay un l\u00edmite f\u00edsico fuerte; su contenedor es otro proceso ejecutado por el usuario root en el kernel de su host. Esto significa que una vulnerabilidad en su aplicaci\u00f3n, el tiempo de ejecuci\u00f3n de Docker o el kernel de Linux podr\u00eda permitir a los atacantes salir del contenedor y realizar operaciones con privilegios de root en su m\u00e1quina.<\/p>\n

Hay algunas protecciones integradas que reducen el riesgo de que esto suceda. La ra\u00edz dentro del contenedor no tiene privilegios y tiene capacidades restringidas. Esto evita que el contenedor use los comandos de administraci\u00f3n del sistema a menos que agregue capacidades manualmente o use el modo privilegiado cuando inicie sus contenedores.<\/p>\n

A pesar de esta mitigaci\u00f3n, permitir que las aplicaciones se ejecuten como ra\u00edz sigue siendo un peligro. Al igual que restringir\u00eda el uso de la ra\u00edz en un entorno tradicional, no es aconsejable usarlo innecesariamente dentro de sus contenedores. Est\u00e1s proporcionando un entorno privilegiado que les da a los atacantes m\u00e1s puntos de apoyo en caso de que ocurra una infracci\u00f3n.<\/p>\n

Ejecuci\u00f3n de aplicaciones en contenedores como usuario no root<\/h2>\n

Es una buena pr\u00e1ctica que las aplicaciones en contenedores se ejecuten como un usuario normal. La mayor\u00eda del software no necesita acceso a la ra\u00edz, por lo que cambiar el usuario proporciona una capa de defensa inmediata contra la ruptura del contenedor.<\/p>\n

Debe crear una nueva cuenta de usuario como una de las etapas finales en su Dockerfile. Puedes lograr esto con el USER<\/code> instrucci\u00f3n:<\/p>\n

FROM base-image:latest
\nRUN apt install demo-package
\nUSER demo-user:demo-group
\nENTRYPOINT [\"demo-binary\"]<\/pre>\n

Los contenedores iniciados a partir de esta imagen se ejecutar\u00e1n como demo-user<\/code>. El usuario ser\u00e1 miembro de la demo-group<\/code> grupo. Puede omitir el nombre del grupo si no necesita que el usuario est\u00e9 en un grupo:<\/p>\n

USER demo-user<\/pre>\n

Puede especificar una ID de usuario (UID) y una ID de grupo (GID) en lugar de nombres:<\/p>\n

USER 950:950<\/pre>\n

La asignaci\u00f3n de un UID y GID conocido suele ser la forma m\u00e1s segura de proceder. Evita que el usuario del contenedor sea asignado a una cuenta de host con privilegios excesivos.<\/p>\n

USER<\/code> a menudo se especifica como la pen\u00faltima etapa en un Dockerfile. Esto significa que a\u00fan puede ejecutar operaciones que requieren root antes en la creaci\u00f3n de la imagen. los apt install<\/code> instrucci\u00f3n en el ejemplo anterior tiene una necesidad leg\u00edtima de root. Si el USER<\/code> la instrucci\u00f3n se coloc\u00f3 encima de \u00e9l, apt<\/code> se ejecutar\u00eda como demo-user<\/code> que carecer\u00eda de los permisos necesarios. Como las instrucciones de Dockerfile solo se aplican a las compilaciones de im\u00e1genes, no a los contenedores en ejecuci\u00f3n, es seguro dejar el cambio de usuario para m\u00e1s adelante en su Dockerfile.<\/p>\n

Cambiar el usuario que ejecuta su contenedor puede requerir que actualice los permisos en los archivos y carpetas a los que accede. Establezca la propiedad en cualquier ruta que utilizar\u00e1 su aplicaci\u00f3n:<\/p>\n

COPY initial-config.yaml \/data\/config.yaml
\n
\nUSER demo-user:demo-group
\nRUN chown demo-user:demo-group \/data<\/pre>\n

En este ejemplo el \/data<\/code> el directorio debe ser propiedad de demo-user<\/code> para que la aplicaci\u00f3n pueda realizar cambios en su archivo de configuraci\u00f3n. El anterior COPY<\/code> declaraci\u00f3n habr\u00e1 copiado el archivo como ra\u00edz. Una forma abreviada est\u00e1 disponible usando el --chown<\/code> bandera con copy<\/code>:<\/p>\n

COPY --chown=demo-user:demo-group initial-config.yaml \/data\/config.yaml<\/pre>\n

Cambiar el usuario al iniciar un contenedor<\/h2>\n

Si bien puede cambiar f\u00e1cilmente el usuario en sus propios Dockerfiles, muchas aplicaciones de terceros contin\u00faan ejecut\u00e1ndose como ra\u00edz. Puede reducir el riesgo asociado con el uso de estos configurando el --user<\/code> marca cada vez que llamas docker run<\/code>. Esto anula el conjunto de usuarios en el Dockerfile de la imagen.<\/p>\n

$ docker run -d --user demo-user:demo-group demo-image:latest
\n$ docker run -d --user demo-user demo-image:latest
\n$ docker run -d --user 950:950 demo-image:latest<\/pre>\n

los --user<\/code> flag ejecuta el proceso del contenedor como el usuario especificado. Es menos seguro que el Dockerfile USER<\/code> instrucci\u00f3n porque tienes que aplicarla individualmente a cada docker run<\/code> dominio. Una mejor opci\u00f3n para las im\u00e1genes de uso regular es crear su propia imagen derivada que pueda establecer una nueva cuenta de usuario:<\/p>\n

FROM image-that-runs-as-root:latest
\nUSER demo-user<\/pre>\n
$ docker build . -t image-that-now-runs-as-non-root:latest<\/pre>\n

Cambiar el usuario de una imagen de terceros puede causar problemas: si el contenedor espera ejecutarse como root o necesita acceder a las rutas del sistema de archivos propiedad del root, ver\u00e1 errores mientras usa la aplicaci\u00f3n. Puede intentar cambiar manualmente los permisos en las rutas que causan problemas. Como alternativa, verifique si el proveedor tiene un m\u00e9todo compatible para ejecutar la aplicaci\u00f3n con una cuenta de usuario sin privilegios.<\/p>\n

Manejo de aplicaciones que tienen que ejecutarse como ra\u00edz<\/h2>\n

El espacio de nombres de usuario es una t\u00e9cnica para tratar con aplicaciones que necesitan algunos privilegios de root. Le permite asignar la ra\u00edz dentro de un contenedor a un usuario no ra\u00edz en su host. La ra\u00edz simulada dentro del contenedor tiene los privilegios que necesita, pero una ruptura no proporcionar\u00e1 acceso de ra\u00edz al host.<\/p>\n

La reasignaci\u00f3n de espacios de nombres se activa agregando un userns-remap<\/code> campo a tu \/etc\/docker\/daemon.json<\/code> expediente:<\/p>\n

\n
\n
\n
\n
\n
\n
\n

\n    \"userns-remap\": \"default\"
\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n

Usando default<\/code> como el valor para userns-remap<\/code> indica a Docker que cree autom\u00e1ticamente un nuevo usuario en su host llamado dockremap<\/code>. La ra\u00edz dentro de los contenedores se asignar\u00e1 de nuevo a dockremap<\/code> en su anfitri\u00f3n. Opcionalmente, puede especificar un usuario y grupo existente en su lugar, utilizando una combinaci\u00f3n de nombre de usuario\/grupo o UID\/GID:<\/p>\n

\n
\n
\n
\n
\n
\n
\n

\n    \"userns-remap\": \"demo-user\"
\n<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n

Reinicie el demonio de Docker despu\u00e9s de aplicar su cambio:<\/p>\n

$ sudo service docker restart<\/pre>\n

si est\u00e1s usando nsuser-remap: default<\/code>la dockremap<\/code> el usuario ahora deber\u00eda existir en su host:<\/p>\n

$ id dockremap
\n
\nuid=140(dockremap) gid=119(dockremap) groups=119(dockremap)<\/pre>\n

El usuario tambi\u00e9n debe aparecer en el \/etc\/subuid<\/code> y \/etc\/subgid<\/code> archivos de ID subordinados:<\/p>\n

$ dockremap:231500:65535<\/pre>\n

Al usuario se le ha asignado un rango de 65\u00a0535 ID subordinados a partir de 231500. Dentro del espacio de nombres de usuario, ID 231500<\/code> est\u00e1 asignado a 0<\/code>, convirti\u00e9ndolo en el usuario ra\u00edz en sus contenedores. Al ser un UID de n\u00famero alto, 231500 no tiene privilegios en el host, por lo que los ataques de ruptura de contenedores no podr\u00e1n infligir tanto da\u00f1o.<\/p>\n

Todos los contenedores que inicie se ejecutar\u00e1n utilizando el espacio de nombres de usuario reasignado a menos que opte por no hacerlo con docker run --userns=host<\/code>. El mecanismo funciona mediante la creaci\u00f3n de directorios con espacios de nombres dentro \/var\/lib\/docker<\/code> que son propiedad del UID y GID subordinado del usuario con espacio de nombres:<\/p>\n

$ sudo ls -l \/var\/lib\/docker\/231500.231500
\n
\ntotal 14
\ndrwx------ 5 231500 231500 13 Jul 22 19:00 aufs
\ndrwx------ 3 231500 231500 13 Jul 22 19:00 containers
\n...<\/pre>\n

El espacio de nombres de usuario es una forma efectiva de aumentar el aislamiento del contenedor, evitar rupturas y preservar la compatibilidad con aplicaciones que necesitan privilegios de ra\u00edz. Sin embargo, existen algunas ventajas y desventajas: la caracter\u00edstica funciona mejor en una instancia nueva de Docker, los vol\u00famenes montados desde el host deben tener sus permisos ajustados y algunos controladores de almacenamiento externo no admiten el mapeo de usuarios en absoluto. Debe revisar la documentaci\u00f3n antes de adoptar esta opci\u00f3n.<\/p>\n

Resumen<\/h2>\n

Ejecutar aplicaciones en contenedores como ra\u00edz es un riesgo de seguridad. Aunque es f\u00e1cil pasarlo por alto, el aislamiento proporcionado por los contenedores no es lo suficientemente s\u00f3lido como para separar por completo a los usuarios del kernel de los usuarios de los contenedores. La ra\u00edz en el contenedor es lo mismo que la ra\u00edz en su host, por lo que un compromiso exitoso podr\u00eda proporcionar el control de su m\u00e1quina.<\/p>\n

Como autor de una imagen, debe incluir la USER<\/code> instrucci\u00f3n en su Dockerfile para que su aplicaci\u00f3n se ejecute sin root. Los usuarios de im\u00e1genes pueden anular esto con docker run --user<\/code> para asignar un UID y GID espec\u00edfico. Esto ayuda a mitigar los casos en los que la imagen normalmente usa la ra\u00edz.<\/p>\n

Puede reforzar a\u00fan m\u00e1s la seguridad eliminando todas las capacidades del contenedor usando --cap-drop=ALL<\/code>luego incluir en la lista blanca aquellos que son necesarios con --cap-add<\/code> banderas La combinaci\u00f3n de estas t\u00e9cnicas ejecutar\u00e1 su aplicaci\u00f3n como un usuario no root con el conjunto m\u00ednimo de privilegios que necesita, mejorando su postura de seguridad.<\/p>\n<\/div>\n