11 maneras (no) de ser víctima de piratería en Kubernetes

Nota perev. : El original de este artículo fue publicado en el blog oficial de Kubernetes y escrito por Andrew Martin, uno de los fundadores de la joven compañía británica Control Plane, especializada en seguridad para aplicaciones nativas en la nube que se ejecutan en K8.



La seguridad en Kubernetes ha recorrido un largo camino desde que llegó el proyecto, pero aún existen dificultades. Ofrecemos una lista de recomendaciones útiles sobre cómo proteger los clústeres y aumentar su estabilidad en caso de piratería: comenzaremos con el plano de control, continuaremos con las cargas de trabajo y la seguridad de la red, y terminaremos con una evaluación de la seguridad futura.

Parte 1: plano de control


El plano de control es el cerebro de Kubernetes. Tiene una idea general de cada contenedor y pod que se ejecuta en el clúster, puede planificar nuevos pod (que pueden contener contenedores con acceso raíz a sus nodos principales) y puede leer todos los secretos almacenados en el clúster. Este es un componente muy importante que necesita protección constante contra la fuga accidental de datos y las acciones maliciosas: tanto cuando se accede a él, cuando no sucede nada y cuando los datos se transmiten a través de la red.

1. TLS ubicuo


Para cada componente que admita TLS, debe estar habilitado, para evitar la detección de tráfico, la verificación de identidad del servidor y (en el caso de Mutual TLS) la verificación de identidad del cliente.

"Tenga en cuenta que algunos componentes y métodos de instalación pueden activar puertos locales para HTTP, por lo que los administradores deben familiarizarse con la configuración de cada componente para identificar posibles rutas para el tráfico inseguro".

De la documentación de Kubernetes

El siguiente diagrama de red de Lucas Käldström muestra dónde se necesita idealmente TLS: entre cada componente en el asistente y entre Kubelet y el servidor API. El clásico Kubernetes The Hard Way de Kelsey Hightower y la documentación de seguridad en etcd ofrecen instrucciones detalladas para lograr estos objetivos.



Históricamente, el escalado automático de los nodos de Kubernetes no fue fácil, ya que cada nodo requería una clave TLS para conectarse al maestro, y guardar secretos en imágenes básicas es una mala práctica. El arranque de Kubelet TLS permite que el nuevo Kubelet cree una solicitud de firma de certificado para que los certificados se generen en el momento del arranque:



2. Privilegios mínimos en RBAC, deshabilitando ABAC, monitoreo de registros


El control de acceso basado en roles (RBAC) proporciona una gestión de políticas precisa por la cual los usuarios acceden a recursos tales como espacios de nombres.



El control de acceso basado en atributos (ABAC) en Kubernetes ha sido reemplazado por RBAC desde K8 1.6 y no debe habilitarse en el lado del servidor de la API. Utilice RBAC en su lugar: --authorization-mode=RBAC (o este indicador para GKE: --no-enable-legacy-authorization -authorification).

Hay muchos buenos ejemplos de políticas RBAC para varios servicios en un clúster, así como documentación . Pero no se detenga ahí: se pueden obtener configuraciones competentes para las políticas de RBAC usando audit2rbac de los registros de audit .

Las políticas de RBAC incorrectas o excesivamente permisivas son un riesgo de seguridad si el hogar se ve comprometido. Mantener las reglas RBAC con privilegios mínimos, auditarlas constantemente y mejorarlas debería ser parte de la "higiene técnica de la deuda" que los equipos aplican en el ciclo de vida del desarrollo.

El registro de auditoría (beta en Kubernetes 1.10) ofrece una API de registro personalizada para cargas de trabajo (como solicitud y respuesta) y en el nivel de metadatos. El nivel de registro se puede configurar de acuerdo con la política de seguridad de la organización: GKE aplica valores predeterminados razonables para aquellos que recién comienzan a trabajar con él.

Para solicitudes de lectura como get , list y watch , solo el objeto solicitado se almacena en registros de auditoría, sin un objeto de respuesta. Para consultas que involucran datos confidenciales como Secret o ConfigMap , solo se exportan los metadatos. Para todas las demás solicitudes, ambos objetos se registran en los registros de auditoría: tanto la solicitud como la respuesta.

No olvide: almacenar estos registros dentro del clúster es un riesgo de seguridad en caso de compromiso. Estos registros, como cualquier otro sensible a la seguridad, deben colocarse fuera del clúster para evitar consecuencias negativas en caso de vulnerabilidad.

3. Utilice la autenticación de terceros para API Server


La centralización de la autenticación y autorización para toda la organización (es decir, Single Sign On) ayuda en los procesos de aceptación y abandono de nuevos empleados, asegurando derechos de acceso consistentes.

La integración de Kubernetes con proveedores de autenticación de terceros (como Google o GitHub) proporciona garantías de identidad desde una plataforma remota (con protección como la autenticación de dos factores) y elimina la necesidad de que los administradores vuelvan a configurar el servidor API en Kubernetes para agregar / eliminar usuarios.

Dex es un proveedor de OpenID Connect Identity (OIDC) y OAuth 2.0 con complementos. Pusher fue aún más lejos al proporcionar herramientas personalizables , además de las cuales hay otros ayudantes enfocados en otras aplicaciones.

4. Separe y coloque su clúster, etc. detrás del firewall


etcd almacena información sobre el estado y los secretos de Kubernetes, es un componente crítico de los K8: debe protegerse por separado del resto del clúster.

El acceso de escritura a etcd en el servidor API es equivalente a la emisión de derechos de root para todo el clúster, e incluso el acceso de lectura se puede usar fácilmente para escalar privilegios.

El planificador de Kubernetes en etcd busca definiciones de pod que no tengan un nodo. Luego envía todas las cápsulas encontradas al Kubelet disponible para su planificación. El servidor API realiza la validación de estos pods antes de escribirlos en etcd, por lo que los atacantes que escriben directamente en etcd pueden eludir muchos mecanismos de seguridad, por ejemplo, PodSecurityPolicies .

etcd debe configurarse con ambos certificados TLS ( cliente y par ) e implementarse en nodos dedicados. Para reducir el riesgo de robo y uso de claves privadas de los nodos de trabajo, también puede limitar el firewall del clúster del servidor API.

5. Rotación de claves de cifrado


La rotación regular de claves y certificados de seguridad es la mejor práctica de seguridad que le permite limitar el "radio de destrucción" cuando la clave se ve comprometida.

Kubernetes rotará automáticamente algunos certificados (en particular, los certificados de cliente y servidor de Kubelet) creando nuevas CSR después de que expiren las actuales.

Sin embargo, las claves simétricas utilizadas por el servidor API para cifrar los valores de etcd no se giran automáticamente, esto debe hacerse manualmente . Esta operación requiere acceso maestro, por lo que los servicios administrados (como GKE y AKS) ocultan el problema al usuario.

Parte 2: cargas de trabajo


Con una seguridad mínima en el plano de control, el clúster ya puede funcionar de forma segura. Sin embargo, como con un barco con carga potencialmente peligrosa, los contenedores de dicha embarcación deben proteger la carga en caso de un accidente o fuga imprevista. Lo mismo es cierto para las cargas de trabajo en Kubernetes ( Pods , Implementaciones , Trabajos , Conjuntos , etc.): se puede confiar en ellos en el momento de la implementación, pero si son accesibles desde el exterior, siempre existe el riesgo de que los [atacantes] los utilicen más tarde. Este riesgo puede mitigarse ejecutando cargas de trabajo con privilegios mínimos y su configuración segura.

6. Use las funciones de seguridad de Linux y PodSecurityPolicies


El kernel de Linux tiene muchas extensiones de seguridad parcialmente superpuestas (capacidades, SELinux, AppArmor, seccomp-bpf) que se pueden configurar para dar a las aplicaciones privilegios mínimos.

Las utilidades como Bane lo ayudarán a generar perfiles para AppArmor, y Docker-Slim lo ayudará a generar perfiles seccomp, pero tenga cuidado: para identificar todos los efectos secundarios de la aplicación de estas políticas, necesita un conjunto de pruebas integral que verifique todo el código de la aplicación.

PodSecurityPolicies rige el uso de estas extensiones de seguridad, así como otras directivas de seguridad de Kubernetes. Son responsables de los requisitos mínimos que deben cumplirse para llegar al servidor API, incluidos los perfiles de seguridad, el indicador de privilegios, la red de host compartida, los procesos o los espacios de nombres para IPC.

Estas directivas son importantes porque ayudan a evitar que los procesos en contenedores escapen de sus límites aislados. El ejemplo de PodSecurityPolicy de Tim Allclair es muy versátil: puede tomarlo como base y personalizarlo para su caso.

7. Realizar un análisis estático de YAML


Si PodSecurityPolicies restringe el acceso al servidor API, el análisis estático también se puede utilizar en el proceso de desarrollo para modelar los requisitos reglamentarios y el apetito de riesgo de la organización.

La información confidencial no debe almacenarse en recursos de YAML como hogares ( Pods , Implementaciones , Conjuntos , etc.), y los ConfigMaps y Secretos confidenciales deben cifrarse con utilidades como Vault (con un operador de CoreOS), git-crypt , secretos sellados o nube KMS proveedor

El análisis estático de la configuración de YAML se puede utilizar como base para la seguridad durante el inicio. Kubesec genera evaluaciones de riesgo para los recursos:

 { "score": -30, "scoring": { "critical": [{ "selector": "containers[] .securityContext .privileged == true", "reason": "Privileged containers can allow almost completely unrestricted host access" }], "advise": [{ "selector": "containers[] .securityContext .runAsNonRoot == true", "reason": "Force the running image to run as a non-root user to ensure least privilege" }, { "selector": "containers[] .securityContext .capabilities .drop", "reason": "Reducing kernel capabilities available to a container limits its attack surface", "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" }] } } 

Y kubetest es un marco para pruebas unitarias de configuraciones de Kubernetes:

 #// vim: set ft=python: def test_for_team_label(): if spec["kind"] == "Deployment": labels = spec["spec"]["template"]["metadata"]["labels"] assert_contains(labels, "team", "should indicate which team owns the deployment") test_for_team_label() 

Estas utilidades implementan el enfoque de desplazamiento a la izquierda (es decir, mueven la validación y la verificación a las primeras etapas del ciclo de desarrollo). Las pruebas de seguridad en la etapa de desarrollo brindan a los usuarios comentarios rápidos sobre el código y la configuración, que luego se pueden rechazar mediante verificación manual o automática, y también pueden facilitar la introducción de prácticas de seguridad adicionales.

8. Ejecute contenedores no root


Los contenedores que se ejecutan como root a menudo tienen muchos más derechos de los que requieren sus cargas de trabajo y, si se ven comprometidos, ayudan a los atacantes a lograr grandes capacidades.

Los contenedores aún dependen del modelo de seguridad tradicional de UNIX (llamado DAC, control de acceso discrecional ): todo es un archivo y se otorgan derechos a usuarios y grupos.

Los espacios de nombres de usuario no funcionan en Kubernetes. Esto significa que la tabla de ID de usuario en el contenedor está asignada a la tabla de usuario del host, y comenzar el proceso con privilegios de root dentro del contenedor hace que se ejecute con privilegios de root en el host. Aunque se agregan mecanismos a todo esto para evitar salir del contenedor, no se recomienda ejecutarlo como root dentro del contenedor.

Muchas imágenes de contenedor utilizan el usuario root para ejecutar PID 1: si este proceso se ve comprometido, el atacante obtiene root en el contenedor y, con cualquier error de configuración, la operación del problema se vuelve mucho más fácil.

Bitnami hizo un gran trabajo al traducir sus imágenes de contenedor a usuarios normales (no root) (que también es el requisito predeterminado de OpenShift), lo que también puede simplificar su migración a imágenes no root.

Este fragmento de PodSecurityPolicy evita que los procesos raíz se ejecuten en el contenedor y escalen a raíz:

 # Required to prevent escalations to root. allowPrivilegeEscalation: false runAsUser: # Require the container to run without root privileges. rule: 'MustRunAsNonRoot' 

Los contenedores que no usan root no pueden ocupar puertos privilegiados, es decir hasta 1024 (la capacidad correspondiente en el kernel de Linux - CAP_NET_BIND_SERVICE es responsable de esto), sin embargo, el uso de los Servicios ayuda a sortear esta limitación. Aquí hay un ejemplo para la aplicación MyApp, que ocupa el puerto 8443 en el contenedor, pero el Servicio lo pone a disposición en el puerto 443, representando solicitudes para targetPort :

 kind: Service apiVersion: v1 metadata: name: my-service spec: selector: app: MyApp ports: - protocol: TCP port: 443 targetPort: 8443 

La necesidad de ejecutar cargas de trabajo sin usar root permanecerá hasta que el espacio de nombres de usuario o el tiempo operativo para iniciar contenedores sin root se incluyan en el tiempo de ejecución del contenedor.

9. Use políticas de red


Por defecto, la red Kubernetes permite todo el tráfico entre pods. Esta configuración puede estar limitada por la política de red: NetworkPolicy .



Los servicios tradicionales están limitados a firewalls que usan direcciones IP estáticas y rangos de puertos para cada servicio. Debido a que estas direcciones IP cambian muy raramente, históricamente se han utilizado como una forma de autenticación. Los contenedores rara vez tienen IP estáticas; su naturaleza implica la posibilidad de una caída rápida y una nueva creación, para ellos se utiliza el descubrimiento de servicios en lugar de direcciones IP estáticas. Estas características complican en gran medida la configuración y verificación de los firewalls.

Como Kubernetes almacena todos los datos sobre el estado del sistema en etcd, es posible configurar un firewall dinámico, si existe el soporte necesario en el complemento de red CNI. Calico, Cilium, kube-router, Romana y Weave Net: todos estos complementos admiten políticas de red.

Es importante tener en cuenta que las políticas funcionan según el principio de falla cerrada, es decir, la ausencia de un podSelector aquí por defecto es igual a todos los valores posibles (comodín):

 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny spec: podSelector: 

El siguiente es un ejemplo de NetworkPolicy , que prohíbe la salida de todo, excepto UDP 53 (DNS), que también impide las conexiones entrantes a la aplicación. NetworkPolicies son políticas con estado , por lo que la aplicación seguirá recibiendo respuestas a las conexiones salientes.

 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: myapp-deny-external-egress spec: podSelector: matchLabels: app: myapp policyTypes: - Egress egress: - ports: - port: 53 protocol: UDP - to: - namespaceSelector: {} 

Las políticas de red de Kubernetes no se pueden aplicar a los nombres DNS. La razón es que el DNS admite la podSelector por turnos para múltiples direcciones IP y respuestas dinámicas que dependen del acceso IP, por lo que las políticas de red se aplican solo a direcciones IP fijas o podSelector (para direcciones IP dinámicas de Kubernetes).

La mejor práctica es comenzar prohibiendo todo el tráfico para el espacio de nombres y agregando paso a paso las rutas requeridas por la aplicación para pasar las pruebas de aceptación. El proceso puede ser difícil, por lo que ControlPlane desarrolló netassert , una utilidad para probar la seguridad de la red en scripts DevSecOps con nmap altamente paralelo:

 k8s: # used for Kubernetes pods deployment: # only deployments currently supported test-frontend: # pod name, defaults to `default` namespace test-microservice: 80 # `test-microservice` is the DNS name of the target service test-database: -80 # `test-frontend` should not be able to access test-database's port 80 169.254.169.254: -80, -443 # AWS metadata API metadata.google.internal: -80, -443 # GCP metadata API new-namespace:test-microservice: # `new-namespace` is the namespace name test-database.new-namespace: 80 # longer DNS names can be used for other namespaces test-frontend.default: 80 169.254.169.254: -80, -443 # AWS metadata API metadata.google.internal: -80, -443 # GCP metadata API 

Una API con metadatos de un proveedor de la nube es una fuente constante de escalada potencial (demostrada por la reciente recompensa de errores de Shopify ), por lo que las pruebas especiales que confirman que la API está bloqueada en la red de contenedores ayudará a proteger contra errores de configuración.

10. Escanee imágenes y ejecute IDS


Los servidores web son un trampolín para atacar las redes a las que están conectados. El escaneo de los archivos instalados en las imágenes le permite verificar que no hay vulnerabilidades conocidas que un atacante pueda usar para obtener acceso remoto al contenedor. Los sistemas de detección de intrusiones (IDS) registran estos eventos si ocurren.

Kubernetes permite envíos al clúster a través de un conjunto de comprobaciones de control (en el controlador de admisión ), que se aplican no solo a los pods, sino también a otros recursos como las implementaciones . En ellos, cada sub se puede validar para la admisión o se puede cambiar su contenido, además de qué webhooks en el lado del backend ahora también son compatibles.



Las herramientas de escaneo de imágenes de contenedor pueden usar estos webhooks para verificar las imágenes antes de implementarlas en el clúster. Las imágenes que no validan no recibirán la aprobación del controlador.

El escaneo de imágenes de contenedores en busca de vulnerabilidades conocidas ayuda a reducir el tiempo que un atacante puede aprovechar un CVE abierto. Para evitar el despliegue de imágenes con vulnerabilidades críticas en la tubería de implementación, puede utilizar utilidades gratuitas como Clair de CoreOS y Micro Scanner de Aqua.

Las herramientas como Grafeas le permiten almacenar metadatos de imágenes para el cumplimiento continuo y las comprobaciones de vulnerabilidad utilizando una firma de contenedor única (o hash especial de direccionamiento de contenido ). Escanear una imagen de contenedor utilizando este hash equivale a escanear imágenes desplegadas en producción y se puede realizar de forma continua sin la necesidad de tener acceso a entornos de producción.

Siempre existirán vulnerabilidades desconocidas de 0 días, por lo que Kubernetes debería implementar un sistema de detección de intrusos como Twistlock , Aqua o Sysdig Secure . IDS detecta un comportamiento inusual en el contenedor y lo detiene o lo mata. Sysdig's Falco es un motor de reglas de código abierto y el punto de partida para este ecosistema.

Parte 3: El Futuro


La siguiente etapa de seguridad en la "evolución de la nube nativa" parece ser la malla de servicios, aunque su adopción no ocurrirá de inmediato: esta migración requiere cambiar la complejidad de las aplicaciones a la infraestructura de malla, y las organizaciones deben realizar esta mejor práctica.



11. Inicie el servicio de malla


La malla de servicio es una red de conexiones encriptadas persistentes hechas entre "conexiones laterales" (similares a "sidecar") , servidores proxy de alto rendimiento como Envoy y Linkerd. Trae gestión de tráfico, monitoreo y políticas, todo sin cambios en los microservicios.

La transferencia de seguridad y código relacionado con la red de microservicios a un conjunto de bibliotecas compartidas y probadas en batalla ya era posible con Linkerd , e Istio de Google, IBM y Lyft trajeron una alternativa a este espacio. Con la adición de SPIFFE para la identidad criptográfica de cada pod y muchas otras características, Istio puede simplificar el despliegue de la seguridad de red de próxima generación.

En las redes de "confianza cero" puede que no sea necesario un firewall tradicional o políticas de red de Kubernetes, ya que cada interacción se produce utilizando mTLS (TLS mutuo), que no solo garantiza la seguridad de la interacción, sino que también confirma la identidad de ambos servicios. .

Este cambio de los enfoques de red tradicionales a los principios de seguridad del mundo de Cloud Native no será fácil para aquellos con una mentalidad de seguridad tradicional. Como introducción a este nuevo mundo, recomendamos encarecidamente el libro Zero Trust Networking de Evan Gilman de SPIFFE.

Istio 0.8 LTS está disponible actualmente, y el proyecto se acerca rápidamente a su versión 1.0. La versión del proyecto en términos de estabilidad se lleva a cabo de manera similar al modelo de Kubernetes: un núcleo estable con API separadas para las cuales su estado alfa o beta se indica mediante espacios de nombres. Espere ver a Istio expandirse en los próximos meses.

Conclusión


Las aplicaciones nativas de la nube tienen un conjunto más detallado de primitivas de seguridad livianas que ayudan a proteger las cargas de trabajo y la infraestructura. El poder y la flexibilidad de tales herramientas es una bendición y una maldición: sin una automatización suficiente [para su uso], exponer las aplicaciones inseguras para ir más allá del contenedor o su modelo de aislamiento se ha vuelto aún más fácil.

Las utilidades para protección son más accesibles que nunca, sin embargo, para reducir el potencial de ataque y el potencial de configuraciones incorrectas, debe usarlas con precaución.

Si la seguridad reduce la velocidad de la organización para generar cambios, nunca será una prioridad. El uso de los principios de entrega continua en relación con la cadena de suministro de software permite a la organización lograr el cumplimiento normativo, la auditoría continua y la gestión mejorada sin afectar el rendimiento del negocio.

La mejora de seguridad rápida e incremental es la forma más fácil con un conjunto de pruebas completo. Continuous Security — pipeline', , , .

PD del traductor


Lea también en nuestro blog:

Source: https://habr.com/ru/post/es417905/


All Articles