Saltar al contenido
Categoria: Forensics9 min de lectura

Container Forensics: Investigando Compromisos en Kubernetes

Por Lucas Andrade ·

Como el equipo Basilisk recolecta evidencia en pods, runtime y control plane tras sospecha de incidente en clusters Kubernetes productivos.

Container Forensics: Investigando Compromisos en Kubernetes
En este artículo

Tres de la manana, alerta de Falco: un pod del namespace payments ejecuto /bin/sh tras abrir un socket reverso hacia una IP extranjera. El equipo de guardia aislo el nodo, pero la primera pregunta del CISO fue brutal: tienen evidencia que sobreviva al kubectl delete pod?. En la mayoria de clusters que Basilisk audita, la respuesta honesta es no. Container forensics en Kubernetes no es una variante de la forensia clasica de host, es una disciplina propia: el runtime recicla layers, cgroups y namespaces mas rapido de lo que cualquier analista logra abrir Wireshark. Esta guia describe una cadena de recoleccion reproducible que arranca antes del incidente y termina con la entrega de evidencia firmada.

Por que la forensia de contenedores es distinta#

Un contenedor no es un servidor pequeno, es un proceso en namespaces aislados sobre un kernel compartido. Su filesystem raiz es un overlay de capas de imagen de solo lectura mas una fina capa superior escribible (el upperdir) que se descarta cuando el pod muere. No hay /var/log persistente, ni contexto estable de uptime, y rara vez un journald dentro del contenedor. Si no recolectas la evidencia donde vive, la pierdes: el scheduler puede mover el pod a otro nodo, un CrashLoopBackOff resetea el estado, y un simple kubectl rollout restart borra el contexto volatil por completo. La madurez forense de un cluster no se mide en herramientas, se mide en el tiempo entre la alerta y la primera copia inmutable.

Modelo de amenaza: vectores dentro del cluster#

Antes de recolectar, prioriza. Los vectores mas comunes son: un contenedor de aplicacion vulnerable con RCE, un token de ServiceAccount robado o sobre-privilegiado desde /var/run/secrets, un breakout del contenedor via privileged: true, montajes hostPath o un bug de kernel, y una supply chain comprometida en la propia imagen. Cada vector deja rastros en una capa distinta: vectores de aplicacion en la memoria del pod, abuso de token en el audit log del kube-apiserver, breakout en el nodo y su arbol de procesos, compromiso de supply chain en las layers de la imagen. El modelo de amenaza decide que capa congelas primero, porque el tiempo es limitado y las capas overlay desaparecen antes.

Preparacion antes del incidente#

La forensia mas efectiva es la preparada. Activa la audit policy del kube-apiserver al menos en nivel Metadata, en RequestResponse para verbos sensibles (exec, attach, portforward, create de objetos RBAC), y envia los logs a un destino externo e inmutable. Programa snapshots horarios de etcd (etcdctl snapshot save) para reconstruir el estado RBAC antes y despues. Manten lista una imagen de toolkit forense (binarios estaticos de busybox, lsof, ss, tcpdump, avml) en un registry separado, y escribe un rol RBAC acotado solo a los respondedores. Sin esta base, cada recoleccion es improvisada y cuestionable en tribunales.

Paso a paso: triaje en vivo en el pod#

La primera capa de evidencia vive en el pod y es volatil por diseno. El orden importa: primero marca el nodo con un taint NoExecute personalizado para que el scheduler no desaloje nada, pero no hagas cordon de inmediato, porque cordon solo no detiene ningun proceso en ejecucion. Dispara un snapshot de disco via CSI (en EKS un snapshot EBS, en GKE gcloud compute disks snapshot), y solo entonces entra al contenedor objetivo con kubectl debug usando una imagen ephemeral con binarios estaticos. Captura /proc/[pid]/exe, /proc/[pid]/maps, /proc/[pid]/environ, sockets abiertos via ss -tanp, y el contenido de /tmp y /dev/shm antes de cualquier reinicio. Quien ya hizo DFIR en Linux: Triaje en Vivo con UAC y Velociraptor en VM tradicional debe adaptar el mindset: aqui la capa superior desaparece en cuanto el pod muere.

Adquisicion de memoria del contenedor#

La memoria del contenedor es el verdadero tesoro porque el malware fileless y el codigo inyectado solo existen ahi. En runtime containerd o CRI-O, el PID del proceso dentro del pod es visible en el host (via crictl inspect o ctr task ls), entonces ejecutas avml --pid <host_pid> o usas LiME compilado contra el kernel exacto del nodo para extraer un dump completo. Ese dump entra directo al flujo de Memory Forensics con Volatility 3: Analizando Dumps en Lab Reproducible, donde linux.pslist, linux.malfind y linux.check_syscall revelan inyecciones que el EDR del host no vio porque estaban confinadas al namespace del contenedor. Cada hash SHA-256 va a una planilla de chain of custody firmada con Sigstore, conectando con la disciplina de Supply Chain Security: Firma con Sigstore y SBOM Real en CI/CD.

Control plane y audit logs#

Subiendo el stack, la investigacion se pone realmente reveladora. El kube-apiserver con audit a nivel RequestResponse graba cada exec, attach y portforward en JSON estructurado, incluyendo user, sourceIPs, userAgent y objectRef. En un caso real de 2025, recuperamos la evidencia decisiva: el atacante creo un ServiceAccount llamado monitoring-helper con cluster-admin via un heredoc kubectl apply -f -; el audit log mostro user-agent kubectl/v1.29.2 desde una IP residencial a las 3:47am. Cruza con snapshots horarios de etcd para reconstruir el estado RBAC antes y despues. Este trabajo de timeline conversa con Timeline Forensics en Windows: Plaso, Log2Timeline y KAPE en la Practica, solo que aplicado a recursos declarativos.

Runtime forensics con eBPF#

La forensia de runtime exige tooling especifico. Instala Tetragon o manten Falco con reglas personalizadas exportando a un SIEM externo, nunca dentro del mismo cluster comprometido. Para captura en vivo, tracee-ebpf de Aqua graba syscalls con contexto de container_id, y sysdig inspect lee archivos .scap como si fueran pcaps de kernel. Cuidado con falsos negativos: si el atacante adapto tecnicas de direct syscalls de Evasion de EDR para Investigacion: Direct Syscalls Explicados sin Romantizar para Linux, o invoca syscalls saltandose la libc, un hook puramente en userspace no ve nada. Un sensor eBPF en el tracepoint del kernel, en cambio, ve el syscall real. Combinado con hunting Sigma al estilo de Threat Hunting con Sigma y Elastic: Del Indicador a la Regla de Deteccion, la chance de pillar el pivote se multiplica.

Network forensics en el CNI#

La network forensics en Kubernetes es distinta de la red tradicional porque el CNI hace NAT y encapsulamiento y la IP del pod se recicla tras su muerte. Captura trafico al nivel del par veth del pod con tcpdump -i any en el host, filtrado por la IP del pod asignada por el IPAM. Si el cluster usa Cilium, hubble observe --pod payments/checkout-7f4 muestra flujos L7 decodificados con contexto de proceso. Para C2 persistente, compara contra IOCs de tu lab de Construyendo Infra de C2 con Sliver en Lab Aislado para Estudio Defensivo y revisa DNS en CoreDNS via query log. Siempre exporta los pcap a storage write-once (WORM u object-lock), porque los abogados aman reclamar integridad.

Diseccionando imagenes comprometidas#

Las imagenes comprometidas merecen capitulo propio. Antes de destruir nada, haz docker save (o skopeo copy) de la imagen sospechosa hacia un registry forense aislado, despues corre dive y trivy fs para mapear archivos anadidos en runtime via kubectl cp o docker exec contra las layers originales. En 60% de los casos que vimos, el atacante no altero la imagen original; dropeo binarios en /tmp o /dev/shm contando con que nadie snapshotearia el overlay. Cuando hay sospecha de compromiso upstream, manda las layers a un lab de Analisis de Malware en Lab Aislado: Setup Seguro con FlareVM y REMnux adaptado para ELF, con Remnux corriendo en VM sin red.

Cadena de custodia y anti-forensia#

El valor probatorio sube y baja con la cadena de recoleccion. Documenta para cada artefacto: que, cuando, de que nodo/pod, con que comando, quien lo recolecto, SHA-256 antes y despues de la transferencia, y guarda todo de forma inmutable. Cuenta con anti-forensia: los atacantes borran /tmp, manipulan el tiempo del contenedor via libfaketime, ocultan procesos con un rootkit LD_PRELOAD, o usan memfd_create para ejecucion fileless que nunca toca disco. Por eso el dump de memoria es innegociable: un proceso sin archivo en disco sigue siendo visible en RAM. Firma cada artefacto con Sigstore/cosign y guarda la clave privada fuera del cluster.

Errores comunes#

Los errores mas caros son de proceso, no tecnicos. kubectl delete pod antes del snapshot destruye la capa overlay de forma irreversible. kubectl exec al contenedor vivo deja tus propios rastros y altera timestamps. Bajar herramientas por la red al nodo comprometido le avisa al atacante que estas ahi. Confiar en el EDR del host como unica fuente ignora todo lo que pasa en el namespace del contenedor. Y guardar evidencia en el mismo cluster que controla el atacante es ingenuo. Ensaya el orden antes de que llegue lo real.

Checklist#

Version corta para la pared del runbook: (1) Taint del nodo NoExecute, congela scheduling. (2) Dispara snapshot de disco CSI. (3) Dump de memoria via avml/LiME contra el kernel del nodo. (4) Captura volatiles del pod: /proc/[pid]/*, sockets, /tmp, /dev/shm. (5) Exporta el audit log del kube-apiserver y un snapshot de etcd. (6) Graba pcap de red en el veth. (7) Guarda la imagen sospechosa via skopeo copy, corre trivy/dive. (8) Hashea todo, firma con Sigstore, guarda en WORM. (9) Escribe la cadena de custodia. (10) Recien entonces contiene (aisla/elimina).

FAQ#

Puedo congelar un contenedor en ejecucion sin matarlo?#

Si. Usa kubectl debug con un contenedor ephemeral en vez de exec, porque comparte el namespace de procesos sin tocar el entrypoint objetivo. A nivel de host puedes pausar el proceso con SIGSTOP (via el PID del host), extraer un dump de memoria y luego decidir si reanudas o contienes. Importante: documenta el SIGSTOP, porque congela el estado y la defensa querra verlo en el reporte.

Alcanza el EDR del host para incidentes de contenedores?#

No. Un EDR de host ve procesos y syscalls, pero sin conciencia de namespaces no los atribuye limpiamente al pod correcto y se pierde inyecciones fileless en la RAM del contenedor. Suma siempre un sensor eBPF con contexto de container_id y un dump de memoria. Nunca dependas de una sola capa.

Conclusion#

Takeaway practico: ensaya el procedimiento antes del incidente. Levanta un cluster kind o k3d, simula un pod atacante que abre una reverse shell, y cronometra cuanto tarda tu equipo entre la alerta y el dump de memoria firmado. Si pasa de 20 minutos, automatiza con un operator que reaccione a eventos Falco aplicando el taint, disparando el snapshot CSI y lanzando un job de coleccion. La forensia de contenedores no es sobre herramientas exoticas, es sobre coreografia ensayada antes de que el escenario se incendie.

Related posts

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly