Container Forensics: Investigando Comprometimentos em Kubernetes
Como a equipe Basilisk coleta evidencia em pods, runtime e control plane apos suspeita de incidente em clusters Kubernetes de producao.

Tres da manha, alerta do Falco: um pod do namespace payments executou /bin/sh apos abrir um socket reverso para um IP estrangeiro. O time de plantao isolou o no, mas a primeira pergunta do CISO foi brutal: voces tem evidencia que sobrevive ao kubectl delete pod?. Na maioria dos clusters que a Basilisk audita, a resposta honesta e nao. Container forensics em Kubernetes nao e uma variacao da forense classica de host, e uma disciplina propria: o runtime recicla layers, cgroups e namespaces mais rapido do que qualquer analista consegue abrir o Wireshark. Este guia descreve uma cadeia de coleta reproduzivel que comeca antes do incidente e termina com a entrega de evidencia assinada.
Por que forense de container e diferente
Um container nao e um servidor pequeno, e um processo em namespaces isolados sobre um kernel compartilhado. Seu filesystem raiz e um overlay de camadas de imagem somente-leitura mais uma fina camada superior gravavel (o upperdir) que e descartada quando o pod morre. Nao ha /var/log persistente, nem contexto estavel de uptime, e raramente um journald dentro do container. Se voce nao coleta a evidencia onde ela vive, voce a perde: o scheduler pode mover o pod para outro no, um CrashLoopBackOff reseta o estado, e um simples kubectl rollout restart apaga o contexto volatil por completo. Maturidade forense num cluster nao se mede em ferramentas, se mede no tempo entre o alerta e a primeira copia imutavel.
Modelo de ameaca: vetores dentro do cluster
Antes de coletar, priorize. Os vetores mais comuns sao: um container de aplicacao vulneravel com RCE, um token de ServiceAccount roubado ou super-privilegiado de /var/run/secrets, um breakout do container via privileged: true, montagens hostPath ou um bug de kernel, e uma supply chain comprometida na propria imagem. Cada vetor deixa rastros em uma camada diferente: vetores de aplicacao na memoria do pod, abuso de token no audit log do kube-apiserver, breakout no no e sua arvore de processos, comprometimento de supply chain nas layers da imagem. O modelo de ameaca decide qual camada voce congela primeiro, porque o tempo e limitado e as camadas overlay somem antes.
Preparacao antes do incidente
A forense mais eficaz e a preparada. Ative a audit policy do kube-apiserver pelo menos em nivel Metadata, em RequestResponse para verbos sensiveis (exec, attach, portforward, create de objetos RBAC), e mande os logs para um destino externo e imutavel. Agende snapshots horarios do etcd (etcdctl snapshot save) para reconstruir o estado RBAC antes e depois. Mantenha uma imagem de toolkit forense pronta (binarios estaticos de busybox, lsof, ss, tcpdump, avml) num registry separado, e escreva uma role RBAC restrita apenas aos respondedores. Sem essa base, toda coleta e improvisada e contestavel em juizo.
Passo a passo: triagem ao vivo no pod
A primeira camada de evidencia vive no pod e e volatil por design. A ordem importa: primeiro marque o no com um taint NoExecute customizado para o scheduler nao despejar nada, mas nao faca cordon de imediato, porque cordon sozinho nao para nenhum processo em execucao. Dispare um snapshot de disco via CSI (no EKS um snapshot EBS, no GKE gcloud compute disks snapshot), e so entao entre no container alvo com kubectl debug usando uma imagem ephemeral com binarios estaticos. Capture /proc/[pid]/exe, /proc/[pid]/maps, /proc/[pid]/environ, sockets abertos via ss -tanp, e o conteudo de /tmp e /dev/shm antes de qualquer reinicio. Quem ja fez DFIR no Linux: Triagem ao Vivo com UAC e Velociraptor em VM tradicional precisa adaptar o mindset: aqui a camada superior some quando o pod morre.
Aquisicao de memoria do container
A memoria do container e o tesouro real porque malware fileless e codigo injetado so existem la. Em runtime containerd ou CRI-O, o PID do processo dentro do pod e visivel no host (via crictl inspect ou ctr task ls), entao voce roda avml --pid <host_pid> ou usa LiME compilado contra o kernel exato do node para extrair um dump completo. Esse dump entra direto no fluxo de Memory Forensics com Volatility 3: Analisando Dumps em Lab Reproduzivel, onde linux.pslist, linux.malfind e linux.check_syscall revelam injecoes que o EDR do host nao viu porque estavam confinadas ao namespace do container. Cada hash SHA-256 vai para uma planilha de chain of custody assinada com Sigstore, conectando com a disciplina de Supply Chain Security: Assinatura com Sigstore e SBOM Real em CI/CD.
Control plane e audit logs
Subindo a stack, a investigacao fica realmente reveladora. O kube-apiserver com audit em nivel RequestResponse grava cada exec, attach e portforward em JSON estruturado, incluindo user, sourceIPs, userAgent e objectRef. Em um caso real de 2025, recuperamos a evidencia decisiva: o atacante criou um ServiceAccount chamado monitoring-helper com cluster-admin via um heredoc kubectl apply -f -; o audit log mostrou user-agent kubectl/v1.29.2 vindo de um IP residencial as 3h47. Cruze com snapshots horarios do etcd para reconstruir o estado RBAC antes e depois. Esse trabalho de timeline conversa com Timeline Forensics no Windows: Plaso, Log2Timeline e KAPE na Pratica, so que aplicado a recursos declarativos.
Runtime forensics com eBPF
Runtime forensics exige ferramental especifico. Instale Tetragon ou mantenha o Falco com regras customizadas exportando para um SIEM externo, nunca para dentro do mesmo cluster comprometido. Para captura ao vivo, o tracee-ebpf da Aqua grava syscalls com contexto de container_id, e o sysdig inspect le arquivos .scap como se fossem pcaps de kernel. Cuidado com falsos negativos: se o atacante adaptou tecnicas de direct syscalls de Evasao de EDR para Pesquisa: Direct Syscalls Explicados sem Romantizacao para Linux, ou invoca syscalls contornando a libc, um hook puramente em userspace nao ve nada. Um sensor eBPF no tracepoint do kernel, por outro lado, ve o syscall real. Combinado com hunting Sigma no estilo de Threat Hunting com Sigma e Elastic: Do Indicador a Regra de Deteccao, a chance de pegar o pivot se multiplica.
Network forensics no CNI
Network forensics em Kubernetes e diferente de rede tradicional porque o CNI faz NAT e encapsulamento e o IP do pod e reciclado apos a morte. Capture trafego no nivel do par veth do pod com tcpdump -i any no host, filtrado pelo IP do pod alocado pelo IPAM. Se o cluster usa Cilium, o hubble observe --pod payments/checkout-7f4 mostra fluxos L7 ja decodificados com contexto de processo. Para C2 persistente, compare com IOCs do seu lab de Construindo Infra de C2 com Sliver em Lab Isolado para Estudo Defensivo e cheque DNS no CoreDNS via query log. Sempre exporte pcap para storage write-once (WORM ou object-lock), porque advogados adoram reclamar de integridade.
Dissecando imagens comprometidas
Imagens comprometidas merecem capitulo proprio. Antes de destruir qualquer coisa, faca docker save (ou skopeo copy) da imagem suspeita para um registry forense isolado, depois rode dive e trivy fs para mapear arquivos adicionados em runtime via kubectl cp ou docker exec contra as layers originais. Em 60% dos casos que vimos, o atacante nao alterou a imagem original; ele dropou binarios em /tmp ou /dev/shm contando que ninguem snapshotaria o overlay. Quando ha suspeita de comprometimento upstream, encaminhe as layers para um lab de Analise de Malware em Lab Isolado: Setup Seguro com FlareVM e Remnux adaptado para ELF, com Remnux rodando em VM sem rede.
Cadeia de custodia e anti-forense
O valor probatorio sobe e desce com a cadeia de coleta. Documente para cada artefato: o que, quando, de qual no/pod, com qual comando, quem coletou, SHA-256 antes e depois da transferencia, e guarde tudo de forma imutavel. Conte com anti-forense: atacantes apagam /tmp, manipulam o tempo do container via libfaketime, escondem processos com um rootkit LD_PRELOAD, ou usam memfd_create para execucao fileless que nunca toca o disco. E exatamente por isso que o dump de memoria e inegociavel: um processo sem arquivo no disco continua visivel na RAM. Assine cada artefato com Sigstore/cosign e mantenha a chave privada fora do cluster.
Erros comuns
Os erros mais caros sao de processo, nao tecnicos. kubectl delete pod antes do snapshot destroi a camada overlay de forma irreversivel. kubectl exec no container vivo deixa seus proprios rastros e altera timestamps. Baixar ferramentas pela rede no no comprometido avisa o atacante que voce esta la. Confiar no EDR do host como unica fonte ignora tudo que acontece no namespace do container. E guardar evidencia no mesmo cluster que o atacante controla e ingenuo. Ensaie a ordem antes do caso real chegar.
Checklist
Versao curta para a parede do runbook: (1) Taint do no NoExecute, congele o scheduling. (2) Dispare snapshot de disco CSI. (3) Dump de memoria via avml/LiME contra o kernel do node. (4) Capture volateis do pod: /proc/[pid]/*, sockets, /tmp, /dev/shm. (5) Exporte o audit log do kube-apiserver e um snapshot do etcd. (6) Grave pcap de rede no veth. (7) Salve a imagem suspeita via skopeo copy, rode trivy/dive. (8) Hasheie tudo, assine com Sigstore, guarde em WORM. (9) Escreva a cadeia de custodia. (10) So entao contenha (isole/apague).
FAQ
Posso congelar um container em execucao sem mata-lo?
Sim. Use kubectl debug com um container ephemeral em vez de exec, porque ele compartilha o namespace de processos sem tocar o entrypoint alvo. No nivel do host voce pode pausar o processo com SIGSTOP (via o PID do host), extrair um dump de memoria e depois decidir se retoma ou contem. Importante: documente o SIGSTOP, porque ele congela o estado e a defesa vai querer ver isso no relatorio.
O EDR do host basta para incidentes de container?
Nao. Um EDR de host ve processos e syscalls, mas sem consciencia de namespaces nao os atribui limpo ao pod certo e perde injecoes fileless na RAM do container. Sempre adicione um sensor eBPF com contexto de container_id e um dump de memoria. Nunca dependa de uma unica camada.
Conclusao
Takeaway pratico: ensaie o procedimento antes do incidente. Monte um cluster kind ou k3d, simule um pod atacante que abre reverse shell, e cronometre quanto tempo seu time leva entre o alerta e o dump de memoria assinado. Se passar de 20 minutos, automatize com um operator que reage a eventos do Falco aplicando o taint, disparando o snapshot CSI e lancando um job de coleta. Forense em containers nao e sobre ferramentas exoticas, e sobre coreografia ensaiada antes do palco pegar fogo.


