En este documento se describen las mitigaciones y respuestas comunes a posibles incidentes de seguridad en los clústeres y contenedores de Google Kubernetes Engine (GKE).
Las sugerencias en la sección Endurecimiento de la seguridad del clúster pueden mejorar la seguridad de tus cargas de trabajo de GKE. Sin embargo, se pueden producir incidentes de seguridad incluso cuando existen medidas para protegerlas.
Detecta incidentes
A fin de detectar posibles incidentes, te recomendamos que configures un proceso que recopile y supervise los registros de tu carga de trabajo. Luego, configura alertas según los eventos anormales detectados en los registros. Las alertas notifican a tu equipo de seguridad si se detecta algo inusual, y, a continuación, ellos pueden revisar el incidente potencial.
Genera alertas a partir de registros
Puedes personalizar alertas según métricas o acciones específicas. Por ejemplo, las alertas sobre el uso elevado de CPU en tus nodos de GKE pueden indicar que existe una vulneración de criptominería.
Las alertas se deben generar en la ubicación en que se agregan los registros y las métricas. Por ejemplo, puedes usar el Registro de auditoría de GKE en combinación con las alertas basadas en registros en Cloud Logging.
Para obtener más información sobre las consultas relacionadas con la seguridad, consulta la documentación de registro de auditoría.
Responde a un incidente de seguridad
Una vez que recibas una alerta sobre un incidente, toma las medidas pertinentes. Si puedes, corrige la vulnerabilidad; si no conoces la causa raíz de la vulnerabilidad o no tienes una solución preparada, aplica medidas de mitigación.
Las mitigaciones que podrías tomar dependen de la gravedad del incidente y de tu certeza de que identificaste el problema.
En esta guía se abordan las acciones que puedes realizar después de detectar un incidente en una carga de trabajo que se ejecuta en GKE. En orden ascendente de gravedad, podrías hacer lo siguiente:
- Crear una instantánea del disco de la VM del host. Una instantánea te permite realizar un análisis forense del estado de la VM en el momento de la anomalía, después de que se haya vuelto a implementar o borrar la carga de trabajo.
Inspeccionar la VM mientras la carga de trabajo continúa ejecutándose. Conectarte a la VM del host o al contenedor de la carga de trabajo puede proporcionarte información sobre las acciones del atacante. Te recomendamos reducir el acceso antes de inspeccionar la VM activa .
Volver a implementar un contenedor. Esto finaliza los procesos que están en ejecución en el contenedor afectado y los reinicia.
Borrar una carga de trabajo. Esto finaliza los procesos que están en ejecución en el contenedor afectado sin un reinicio.
Estas mitigaciones se describen en las secciones siguientes.
Antes de comenzar
Los métodos utilizados en este tema usan la siguiente información:
- El nombre de los pods que crees que fueron vulnerados o
POD_NAME
- El nombre de la VM del host que ejecuta el contenedor o los pods, o
NODE_NAME
Además, antes de tomar cualquiera de estas medidas, considera si el atacante reaccionará negativamente si se da cuenta que lo descubriste. El atacante puede decidir borrar datos o destruir cargas de trabajo. Si el riesgo es demasiado alto, considera mitigaciones más drásticas, como borrar una carga de trabajo antes de realizar una investigación más exhaustiva.
Haz una instantánea del disco de la VM
Crear una instantánea del disco de la VM permite realizar una investigación forense después de que la carga de trabajo se vuelva a implementar o se borre. Las instantáneas se pueden crear mientras los discos están conectados a instancias en ejecución.
Para crear una instantánea de tu disco persistente, primero busca los discos conectados a tu VM. Ejecuta el siguiente comando y observa el campo
source
:gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \ --format="flattened([disks])"
Busca las líneas que contengan
disks[NUMBER].source
. La salida es similar a lo siguiente:disks[0].source: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/COMPUTE_ZONE/disks/DISK_NAME
El nombre del disco es la parte del nombre de la fuente después de la barra final. Por ejemplo, el nombre del disco es
gke-cluster-pool-1-abcdeffff-zgt8
.Para completar la instantánea, ejecuta el siguiente comando:
gcloud compute disks snapshot DISK_NAME
Para obtener más información, consulta Crea instantáneas de disco persistente en la documentación de Compute Engine.
Inspecciona la VM mientras se ejecuta la carga de trabajo
También debes considerar qué tipo de acceso puede tener un atacante antes de tomar medidas. Si sospechas que se vulneró un contenedor y te preocupa informar al atacante, puedes conectarte al contenedor para inspeccionarlo. Las inspecciones son útiles para realizar una investigación rápida antes tomar medidas más disruptivas. La inspección también es el enfoque menos perjudicial para la carga de trabajo, pero no detiene el incidente.
Como alternativa, para evitar el acceso a una máquina con una credencial privilegiada, puedes analizar tus cargas de trabajo mediante la configuración de análisis forense en tiempo real (como GRR Rapid Response), agentes en nodo o filtros de red.
Reduce el acceso antes de inspeccionar la VM activa
Si acordonas, purgas y limitas el acceso de red a la VM que aloja un contenedor comprometido, puedes aislar parcialmente el contenedor comprometido del resto de tu clúster. Limitar el acceso a la VM reduce el riesgo, pero no evita que un atacante se desplace lateralmente en tu entorno si aprovecha una vulnerabilidad crítica.
Acordona el nodo y purga de él las otras cargas de trabajo
Acordonar y purgar un nodo traslada las cargas de trabajo ubicadas en el contenedor vulnerado a otras VM de tu clúster. Acordonar y purgar reduce la capacidad de un atacante de afectar otras cargas de trabajo en el mismo nodo, pero no necesariamente se evita que inspeccione el estado persistente de una carga de trabajo (por ejemplo, si inspecciona el contenido de la imagen del contenedor).
Usa
kubectl
para acordonar el nodo y asegurarte de que no haya otros pods programados en él:kubectl cordon NODE_NAME
Después de acordonar el nodo, púrgalo de otros pods.
Etiqueta el Pod que estás poniendo en cuarentena:
kubectl label pods POD_NAME quarantine=true
Reemplaza
POD_NAME
por el nombre del Pod que deseas poner en cuarentena.Purga el nodo de los pods que no están etiquetados con
quarantine
:kubectl drain NODE_NAME --pod-selector='!quarantine'
Restringe el acceso de red al nodo
Recomendamos bloquear el acceso de tráfico interno y externo a la VM del host. A continuación, permite que las conexiones entrantes de una VM específica en tu red o VPC se conecten a la VM en cuarentena.
El primer paso es abandonar la VM del Grupo de instancias administrado que la posee. Abandonar la VM impide que el nodo se marque como en mal estado y se repare automáticamente (se vuelva a crear) antes de que se complete la investigación.
Para abandonar la VM, ejecuta el siguiente comando:
gcloud compute instance-groups managed abandon-instances INSTANCE_GROUP_NAME \
--instances=NODE_NAME
Usa un firewall en la VM
Crear un firewall entre el contenedor afectado y otras cargas de trabajo en la misma red ayuda a evitar que un atacante se desplace a otras partes de tu entorno mientras realizas más análisis. Como ya purgaste la VM de otros contenedores, esto solo afecta al contenedor en cuarentena.
Las siguientes instrucciones sobre la creación de firewall de la VM evitan lo siguiente:
- Nuevas conexiones de salida a otras VM en tu clúster con una regla de salida
- Conexiones entrantes a la VM comprometida mediante una regla de entrada
A fin de proteger la VM de tus otras instancias, sigue estos pasos para el nodo que aloja el pod que deseas poner en cuarentena:
Etiqueta la instancia a fin de poder aplicar una nueva regla de firewall.
gcloud compute instances add-tags NODE_NAME \ --zone COMPUTE_ZONE \ --tags quarantine
Crea una regla de firewall para denegar todo el tráfico de TCP de salida de las instancias con la etiqueta
quarantine
:gcloud compute firewall-rules create quarantine-egress-deny \ --network NETWORK_NAME \ --action deny \ --direction egress \ --rules tcp \ --destination-ranges 0.0.0.0/0 \ --priority 0 \ --target-tags quarantine
Crea una regla de firewall para denegar todo el tráfico de TCP de entrada a instancias con la etiqueta
quarantine
. Asigna a esta regla de entrada unapriority
de1
, que te permite anularla con otra regla que permita SSH desde una VM especificada.gcloud compute firewall-rules create quarantine-ingress-deny \ --network NETWORK_NAME \ --action deny \ --direction ingress \ --rules tcp \ --source-ranges 0.0.0.0/0 \ --priority 1 \ --target-tags quarantine
Quita la dirección IP externa de la VM
Si quitas la dirección IP externa de la VM, se interrumpen todas las conexiones de red existentes fuera de tu VPC.
Para quitar la dirección externa de una VM, realiza los siguientes pasos.
Busca y borra la configuración de acceso que asocia la IP externa con la VM. En primer lugar, busca la configuración de acceso mediante la descripción de la VM:
gcloud compute instances describe NODE_NAME \ --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"
Busca las líneas que contienen
name
ynatIP
. Son similares a las siguientes:networkInterfaces[0].accessConfigs[0].name: ACCESS_CONFIG_NAME networkInterfaces[0].accessConfigs[0].natIP: EXTERNAL_IP_ADDRESS
Busca el valor de
natIP
que coincida con la IP externa que deseas quitar. Ten en cuenta el nombre de la configuración de acceso.Para quitar la IP externa, ejecuta el siguiente comando:
gcloud compute instances delete-access-config NODE_NAME \ --access-config-name "ACCESS_CONFIG_NAME"
Crea una conexión SSH a la VM del host mediante una VM intermedia
Después de quitar la IP externa de la VM del host, no puedes crear una conexión SSH fuera de tu VPC; debes acceder desde otra VM de la misma red. En el resto de esta sección, nos referiremos a esto como la VM intermedia.
Requisitos previos
- Una VM intermedia con acceso a la subred de la VM del host; si aún no la tienes, crea una para este fin
- La dirección IP interna de la VM intermedia
- Una clave pública SSH de la VM intermedia. Para obtener más información, consulta Administra llaves SSH
Conéctate a la VM del host
- Agrega la clave pública de la VM intermedia a la VM del host. Para obtener más información, consulta cómo agregar y quitar llaves SSH en la documentación de Compute Engine.
Agrega una etiqueta a la VM intermedia.
gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \ --zone COMPUTE_ZONE \ --tags intermediate
Agrega una regla de permiso de entrada para anular la regla de denegación que agregaste antes. Para agregar la regla, ejecuta el siguiente comando:
gcloud compute firewall-rules create quarantine-ingress-allow \ --network NETWORK_NAME \ --action allow \ --direction ingress \ --rules tcp:22 \ --source-tags intermediate \ --priority 0 \ --target-tags quarantine
Esta regla permite el tráfico entrante en el puerto 22 (SSH) de las VM de tu red con la etiqueta
intermediate
. Además, anula la regla de denegación con unapriority
de0
.Conéctate a la VM en cuarentena con su IP interna:
ssh -i KEY_PATH USER@QUARANTINED_VM_INTERNAL_IP
Reemplaza lo siguiente:
KEY_PATH
: Es la ruta de acceso a la llave privada SSH.USER
: La dirección de correo electrónico de tu cuenta de Google CloudQUARANTINED_VM_INTERNAL_IP
: Es la dirección IP interna.
Vuelve a implementar el contenedor
Cuando implementas de nuevo un contenedor, inicias una copia nueva de este y borras el contenedor afectado.
Para volver a implementar un contenedor, borra el pod que lo aloja. Si el pod es administrado por una construcción de Kubernetes de nivel superior (por ejemplo, una Implementación o DaemonSet), borrar el pod programa un pod nuevo. Este pod ejecuta contenedores nuevos.
Volver a realizar la implementación se recomienda en los siguientes casos:
- Ya conoces la causa de la vulnerabilidad.
- Crees que a un atacante le costaría mucho tiempo o esfuerzo volver a comprometer tu contenedor.
- Crees que el contenedor podría volver a comprometerse con rapidez y no quieres que se desconecte, por lo que planeas colocarlo en una zona de pruebas para limitar el impacto.
Cuando vuelvas a implementar la carga de trabajo, si la posibilidad de otro compromiso es alta, considera colocar la carga de trabajo en un entorno de zona de pruebas, como GKE Sandbox. Las zonas de pruebas limitan el acceso al kernel del nodo host si el atacante vuelve a comprometer el contenedor.
Para volver a implementar un contenedor en Kubernetes, borra el pod que lo contiene.
kubectl delete pods POD_NAME --grace-period=10
Si los contenedores del pod borrado siguen ejecutándose, puedes borrar la carga de trabajo.
Para volver a implementar el contenedor dentro de una zona de pruebas, sigue las instrucciones en Endurece el aislamiento de la carga de trabajo con GKE Sandbox.
Borra una carga de trabajo
Si borras una carga de trabajo, como una Implementación o un DaemonSet, se borrarán todos sus pods miembros. Todos los contenedores dentro de esos pods dejarán de ejecutarse. Borrar una carga de trabajo puede recomendarse en los siguientes casos:
- Deseas detener un ataque en curso.
- Estás dispuesto a realizar la carga de trabajo sin conexión.
- Detener el ataque de inmediato es más importante que el tiempo de actividad de la aplicación o el análisis forense.
Para borrar una carga de trabajo, usa kubectl delete CONTROLLER_TYPE
.
Por ejemplo, para borrar una Implementación, ejecuta el siguiente comando:
kubectl delete deployments DEPLOYMENT
Si cuando borras la carga de trabajo no se borran todos los pods o contenedores asociados, puedes borrar de forma manual los contenedores con la herramienta de CLI del entorno de ejecución del contenedor, normalmente docker
. Si tus nodos ejecutan containerd, usa crictl
.
Docker
Para detener el contenedor mediante el entorno de ejecución del contenedor de Docker, puedes usar docker stop
o docker kill
.
A fin de detener el contenedor, docker stop
envía una señal SIGTERM
al proceso raíz y espera 10 segundos para salir del proceso de forma predeterminada. Si el proceso no finaliza en ese período, se envía una señal SIGKILL
.
Puedes especificar este período de gracia con la opción --time
.
docker stop --time TIME_IN_SECONDS CONTAINER
docker kill
es el método más rápido para detener un contenedor. Envía la señal SIGKILL
de inmediato.
docker kill CONTAINER
También puedes detener y quitar un contenedor en un comando con docker rm -f
docker rm -f CONTAINER
containerd
Si usas el entorno de ejecución de containerd
en GKE, detienes o quitas contenedores con crictl
.
Para detener un contenedor en containerd
, ejecuta el siguiente comando:
crictl stop CONTAINER
Para quitar un contenedor en containerd
, ejecuta el siguiente comando:
crictl rm -f CONTAINER
Borra la VM del host
Si no puedes borrar o quitar el contenedor, puedes borrar la máquina virtual que aloja el contenedor afectado.
Si el pod aún es visible, puedes encontrar el nombre de la VM del host con el siguiente comando:
kubectl get pods --all-namespaces \
-o=custom-columns=POD_NAME:.metadata.name,INSTANCE_NAME:.spec.nodeName \
--field-selector=metadata.name=POD_NAME
Para borrar la VM del host, ejecuta el siguiente comando de gcloud
:
gcloud compute instance-groups managed delete-instances INSTANCE_GROUP_NAME \
--instances=NODE_NAME
Abandonar la instancia del grupo de instancias administrado reduce el tamaño del grupo en una VM. Puedes volver a agregar una instancia de forma manual al grupo con el siguiente comando:
gcloud compute instance-groups managed resize INSTANCE_GROUP_NAME \
--size=SIZE
¿Qué sigue?
- Cómo realizar análisis forenses en contenedores
- Endurece la seguridad del clúster
- Análisis forense para aplicaciones de GKE