Docker como caja de arena para código no confiable

32

He creado una aplicación web que, entre otras cosas, permite a los usuarios escribir, compilar y ejecutar código (Java, C #). La aplicación crea un contenedor Docker para cada usuario donde se lleva a cabo la compilación y la ejecución del código. He tomado las siguientes medidas para asegurar el contenedor:

  • Este contenedor no tiene datos persistentes o compartidos
  • No tiene acceso a la API de la ventana acoplable (que está protegida con TLS)
  • No hay información dentro del contenedor que el usuario no deba conocer
  • El usuario no sabrá que el compilador está dentro de un contenedor

¿Puedo considerar que este contenedor es seguro para ejecutar código no confiable? ¿Hay alguna forma conocida de efectuar la máquina host desde el contenedor en una configuración como esta?

    
pregunta Hartger 11.12.2015 - 11:28
fuente

3 respuestas

28

tl; dr : las soluciones de contenedor no garantizan y nunca garantizarán el aislamiento completo; en su lugar, utilice la virtualización si lo necesita.

Enfoques de abajo hacia arriba y de arriba hacia abajo

Docker (y lo mismo se aplica a soluciones de contenedores similares) no garantiza un aislamiento completo y no se puede confundir con la virtualización. El aislamiento de contenedores se logra al agregar algunas barreras entre ellos, pero Aún utilizamos recursos compartidos como el kernel. Por otro lado, la virtualización tiene recursos compartidos mucho más pequeños, que ahora son más fáciles de entender y están bien probados, a menudo enriquecidos por las características de hardware para restringir el acceso. Docker describe esto en su artículo de seguridad de Docker como

  

Un riesgo principal al ejecutar contenedores de Docker es que el conjunto predeterminado de capacidades y montajes otorgados a un contenedor puede proporcionar un aislamiento incompleto, ya sea de forma independiente o cuando se usa en combinación con las vulnerabilidades del kernel.

Considere la virtualización como un enfoque de arriba hacia abajo

Para la virutalización, comienza con un aislamiento bastante completo y proporciona algunas interfaces bien descritas y bien guardadas; esto significa que puede estar bastante seguro de que salir de una máquina virtual es difícil. El kernel no se comparte, si tiene alguna vulnerabilidad de kernel que le permita escapar de las restricciones de los usuarios, el hipervisor se interpone entre usted y otras máquinas virtuales.

Esto no implica un aislamiento perfecto. Una y otra vez, se encuentran problemas con el hipervisor, pero la mayoría son ataques muy complicados con un alcance limitado que son difíciles de realizar (pero también son muy críticos, "fáciles de explotar").

Los contenedores, por otro lado, están de abajo hacia arriba

Con los contenedores, comienzas ejecutando aplicaciones en el mismo kernel, pero agregas barreras (espacios de nombres del kernel, cgroups, ...) para aislarlos mejor. Si bien esto proporciona algunas ventajas como una menor sobrecarga, es mucho más difícil "estar seguro" de no haber olvidado nada, el Kernel de Linux es una pieza de software muy grande y compleja. Y el kernel en sí todavía se comparte, si hay una vulnerabilidad en el kernel, es muy probable que pueda escapar al host (y / u otros contenedores).

Usuarios dentro y fuera de contenedores

Especialmente antes de Docker 1.9 que debería obtener los espacios de nombres de los usuarios significa que "la raíz del contenedor también tiene privilegios de raíz de host "tan pronto como se encuentre otra barrera faltante en la máquina Docker (o la vulnerabilidad del núcleo). Ha habido tales problemas antes , debe esperar más por venir y Docker recomienda que

  

tenga cuidado de ejecutar sus procesos dentro de los contenedores como usuarios sin privilegios (es decir, no root).

Si está interesado en obtener más detalles, estep publicó un buen artículo en http://integratedcode.us que explica los espacios de nombres de los usuarios .

Restringir el acceso de root (por ejemplo, imponer a un usuario sin privilegios al crear la imagen o al menos usar los nuevos espacios de nombres de usuario) es una medida de seguridad básica y necesaria para proporcionar aislamiento, y puede dar a la satisfacción de aislamiento entre contenedores. El uso de espacios de nombres de usuarios y usuarios restringidos, el escape al host se vuelve mucho más difícil, pero aún así no debería estar seguro de que no haya otra forma de salir de un contenedor (y si esto incluye explotar un problema de seguridad no parcheado en el kernel ), y no debe utilizarse para ejecutar código no confiable.

    
respondido por el Jens Erat 11.12.2015 - 12:02
fuente
12

Si bien la respuesta de @ jens-erat tiene el punto correcto de alto nivel que la virtualización proporciona un aislamiento superior a las soluciones de contenedorización Al igual que la ventana acoplable, no es una configuración en blanco y negro.

Por un lado, ha habido un número de invitados - > host breakouts en tecnología de virtualización (por ejemplo, la vulnerabilidad " Venom " en los controladores de dispositivos de disquete virtuales), así como cualquier control de seguridad, el aislamiento proporcionado por la virtualización no es 100%.

En la perspectiva de fortalecer su instalación de la ventana acoplable para mejorar el aislamiento y reducir el riesgo que se presenta, hay una serie de pasos que puede tomar para ayudar a asegurar su instalación de la ventana acoplable.

  1. Docker tiene una buena guía de seguridad disponible sobre el endurecimiento. Hay una (un poco desactualizada) Guía de seguridad de CIS y también docker bench que se puede usar para revisar las configuraciones

  2. Dependiendo de cómo funcione su aplicación (es decir, cómo se adhiere el código allí para la compilación), puede modificar la operación de la ventana acoplable para reducir las posibilidades de actividad maliciosa. Por ejemplo, suponiendo que el código llegue allí en el nivel de host, puede negar el acceso de red al contenedor ( --net none switch en docker run ). También puede ver si puede eliminar capacidades adicionales para reducir el proceso que se ejecuta en el contenedor puede hacer.

  3. Considere usar los perfiles de AppArmor para restringir los recursos. AppArmor se puede usar para restringir lo que se puede hacer en el contenedor y puede usar herramientas como bane para generar perfiles para sus aplicaciones.

  4. También recomendaría implementar cierta supervisión en el nivel de host para buscar posibles accesos maliciosos. Como usted sabe lo que deberían o no deberían estar haciendo los contenedores, tener un monitoreo relativamente estricto lo alertaría de cualquier posible ruptura

Otra área que podría ser productiva para fortalecer este tipo de configuración es usar imágenes de sistema operativo y de contenedor simplificadas. Cuanto menor sea el código expuesto, menor será la superficie de ataque. Algo como CoreOS o Ubuntu Snappy Core podría valer la pena mirar

    
respondido por el Rоry McCune 13.12.2015 - 13:03
fuente
1

Mi solución sería algo así como SmartOS. La razón de ser SmartOS es compatible con Docker, KVM y zonas. Por lo tanto, podría usarlos en combinación para evitar que se ejecuten códigos maliciosos más allá de un contenedor Docker. Después de todo, los contenedores Docker son todavía archivos en un sistema de archivos.

    
respondido por el Christo Goosen 31.07.2018 - 11:14
fuente

Lea otras preguntas en las etiquetas