Panorama: la ventaja que cambia la economía del problema#

El capítulo anterior terminó con un problema caro. La detección de persistencia en un host Linux se apoyaba en una línea base de auto-ejecución que hay que construir, versionar y mantener contra un sistema de propósito general donde el software legítimo escribe en los mismos lugares que el adversario. Finito no era pequeño: la parte difícil no era saber dónde mirar sino sostener el conocimiento de qué debería estar ahí.

El contenedor invierte esa economía, y esa inversión es la primera mitad de la tesis de este capítulo. Un contenedor de propósito único tiene un conjunto de comportamiento permitido tan reducido que la línea base deja de ser un proyecto y pasa a derivarse de la definición del workload. Una imagen que existe para servir una API en Go ejecuta un binario, escucha en un puerto y habla con una base de datos; no compila nada, no abre intérpretes de comandos, no lee /etc/shadow y no monta sistemas de archivos. En un servidor de propósito general, «se lanzó un intérprete de comandos» es ruido puro —ocurre miles de veces por día y casi siempre es legítimo—. En un contenedor de producción es una de las señales más limpias que existen en toda la seguridad defensiva: fidelidad casi perfecta, sin listas de excepciones que mantener, y sin la fatiga de alertas que 5.1 identificaba como la enfermedad crónica del SOC. Es la razón por la que el disparo emblemático del IDS cloud-native«a shell was spawned in a container with an attached terminal»— vale tanto con una regla tan simple.

La segunda mitad de la tesis corrige el entusiasmo. Un sensor de host, por bueno que sea, cubre solo la mitad del problema, porque Kubernetes tiene dos planos y el adversario puede operar entero en el que ningún sensor de endpoint observa. El plano de datos son las cargas de trabajo corriendo en los nodos, y ahí el IDS de runtime es el instrumento. El plano de control es el API server: quien roba el token de un service account —que 3.16 señalaba como la vía de escalada número uno— no ejecuta nada en ningún nodo. Enumera permisos, lee secrets, crea recursos y despliega cargas de trabajo, todo mediante peticiones HTTP autenticadas contra una API. No hay proceso anómalo que interceptar, no hay archivo que cambie, no hay syscall sospechosa. Es exactamente la situación de 5.9 con la exfiltración nativa de SaaS: actividad plenamente maliciosa que no aparece en ninguna telemetría de endpoint, y cuya única fuente es el registro de auditoría del servicio.

Y hay un tercer elemento que reordena el resto: la efimeridad. El host de 5.10 seguía ahí cuando alguien decidía auditarlo. Un pod puede haber sido reprogramado, terminado y reemplazado por el propio orquestador antes de que un analista abra la alerta que generó. Eso no cambia qué se detecta, pero cambia radicalmente cómo se responde y qué queda para investigar.

Por qué el sensor de 5.10 no se traslada#

5.10 dejó dicho de pasada el motivo y conviene desarrollarlo, porque es lo que fuerza toda la arquitectura siguiente: auditd no entiende espacios de nombres. La herramienta es anterior a los contenedores y su modelo mental es una máquina con usuarios y procesos. Cuando en un nodo que corre cuarenta pods se registra un execve, auditd informa un identificador de proceso y un usuario del host —y traducir eso a «qué contenedor, de qué pod, de qué deployment, de qué equipo» es un trabajo de correlación externo, frágil y parcial. Sin esa traducción, la alerta no es accionable: nadie puede responder a «hubo un bash en el nodo 12».

Lo mismo le pasa al FIM. Vigilar los archivos del nodo no dice nada de lo que ocurre dentro de la raíz de un contenedor, y la vigilancia dentro del contenedor tropieza con una propiedad que en este modelo es una ventaja: el sistema de archivos del contenedor es efímero, así que un cambio dentro de él no sobrevive al reinicio. Esto es una buena noticia defensiva —3.16 ya lo señalaba: la persistencia tradicional no funciona igual, el adversario tiene que subir al plano de control o bajar al nodo— pero deja al FIM sin objeto. El conjunto de disparadores enumerables que hacía tratable a 5.10 no existe con la misma forma acá.

Queda además el efecto de la inmutabilidad, que es aprovechable si se lo declara. Una imagen de contenedor es un artefacto fijo y conocido: cualquier binario que se ejecute y que no venga de la imagen es, por construcción, algo que alguien introdujo en tiempo de ejecución. Ese es el equivalente contenerizado —y bastante más fuerte— de la verificación contra paquetes que 5.10 recomendaba, y es lo que permite montar el sistema de archivos como solo lectura y convertir cualquier escritura en un evento en lugar de un dato.

eBPF: el sensor correcto y sus tres límites#

La respuesta a la ceguera de auditd es el IDS basado en eBPF, que ejecuta código verificado dentro del kernel y observa las syscalls con el contexto de espacio de nombres y de grupo de control. Esa última propiedad es la que importa: no es que vea más eventos, es que puede atribuirlos a la carga de trabajo correcta, que era justo lo que faltaba. Falco —y su par Tracee— son la referencia: interceptan execve, open y compañía, y evalúan un catálogo de reglas. Las de comunidad ya cubren lo esencial: procesos permitidos por contenedor, puertos de entrada esperados por componente del plano de control, escritura en rutas que deberían ser de solo lectura, montajes sensibles.

Hay una elección de diseño que conviene explicitar. El IDS clásico contrapone firma y anomalía: la firma es liviana pero ciega ante lo nuevo; la anomalía cubre lo desconocido pero es más costosa y —el problema real— obliga al defensor a definir qué es «correcto», lo que traslada a él toda la carga. Ese ha sido históricamente el argumento en contra de la detección por anomalía. En contenedores ese argumento se debilita mucho, y por la razón del panorama: definir el comportamiento correcto de un pod de propósito único es factible, y en buena medida ya está hecho en su manifiesto. La detección por anomalía es cara donde el sistema es de propósito general; acá el sistema colabora.

Dicho lo cual, corresponde el mismo rigor que 5.8 aplicó a la medición de sensores. El IDS de runtime tiene tres límites y ninguno es un defecto de implementación:

  • Las reglas son código, y el código tiene errores. El caso documentado es ejemplar: un investigador encontró que una regla de Falco que identificaba imágenes confiables comparaba por prefijo de repositorio, de modo que una imagen alojada bajo un nombre de organización terminado en la cadena esperada satisfacía la comparación. El resultado era desplegar un agente privilegiado propio sin generar una sola alerta. La lección es la de 5.8 sin cambios: una regla no está terminada cuando se escribe, sino cuando se verificó que dispara —y el catálogo entero, incluido el heredado de la comunidad, hay que validarlo con pruebas dirigidas en vez de darlo por correcto porque existe—. Es el ejercicio purple en su forma más concreta.
  • El sensor tiene superficie de ataque propia. eBPF corre en el kernel con privilegio, su verificador ha tenido fallos explotables que permitieron evadir sus comprobaciones de límites, y —como ya advertía 5.10— frente a un adversario que ya está en el kernel no goza de inmunidad especial: comparte dominio de confianza con él. Su ventaja decisiva no es ser inviolable, es observar el ataque mientras se instala, antes de que exista nada que lo subvierta.
  • Para detectar el escape hay que desplegar algo capaz de escapar. El agente necesita privilegio sobre el nodo —capacidades de eBPF y visibilidad del espacio de procesos del host—, es decir, exactamente el perfil que 3.16 describía como precursor de casi todo breakout. Esa tensión no se resuelve, se administra: el agente de seguridad es un objetivo de alto valor, su imagen y su cadena de suministro merecen el escrutinio más estricto del clúster, y su capacidad de despliegue debe estar entre las más restringidas por política.

El plano de control: la mitad que ningún sensor de host ve#

El audit log del API server registra cada petición contra la API, con quién la hizo, qué pidió y qué respondió el servidor. Es, para el plano de control, lo que la telemetría de 5.2 era para el host: la capa de datos sin la cual todo lo demás es conjetura. Y sigue siendo, en la mayoría de los despliegues reales, la brecha de cobertura más grande —el mismo hallazgo que 5.9 hacía con los registros de auditoría de SaaS, por la misma causa: no está apagado por malicia ni por descuido, está apagado porque nadie lo incluyó en el alcance del SIEM.

Su configuración es una decisión de costo contra visibilidad —los niveles van desde no registrar nada hasta registrar petición y respuesta completas—, y ahí conviene ser deliberado en lugar de aceptar el valor por defecto: registrar cuerpos completos de todo es caro e innecesario, pero registrar solo metadatos deja sin respuesta la pregunta de qué contenía exactamente el recurso que el adversario creó.

Lo que se caza en esa fuente tiene una forma reconocible:

  • Un service account pidiendo lo que su carga de trabajo nunca pide. El caso canónico es la identidad default de un pod solicitando la totalidad de los secrets del espacio de nombres. La señal es la misma que 5.9 aislaba en la exfiltración por API y merece repetirse porque es transversal: la aplicación legítima llama a un conjunto acotado y estable de recursos propios; el adversario recorre el árbol. Enumerar permisos, listar espacios de nombres, listar secrets —esa secuencia es descubrimiento, y el descubrimiento es la fase más temprana y más barata de detectar.
  • Acceso interactivo a producción. Las peticiones de tipo exec y attach contra un pod son el equivalente de abrir una sesión en un servidor de producción. En muchas organizaciones son legítimas pero poco frecuentes, lo que las convierte en una señal de alta fidelidad por infrecuencia —el mismo criterio que hacía valioso al 7045 en 5.6—.
  • Identidades y orígenes fuera de patrón. Un token de service account usado desde fuera del clúster, un agente de usuario que revela una herramienta de línea de comandos donde solo debería haber tráfico de controladores, actividad a horas en las que ese componente no opera.

Y aquí aparece la propiedad más aprovechable del modelo, que no tiene equivalente en un host tradicional: en Kubernetes el ataque se declara antes de ejecutarse. El pod privilegiado que va a montar el disco del nodo, el que pide el espacio de procesos del host, el que monta una ruta sensible del sistema de archivos —todos los precursores de escape que 3.16 catalogó— pasan primero por la API como un manifiesto, en texto, y el registro de auditoría los ve antes de que el contenedor arranque. El adversario tiene que anunciar su intención en un formato estructurado y legible para poder llevarla a cabo. En un servidor tradicional no existe un punto donde la ejecución se declare antes de ocurrir; acá sí, y de ahí que la frontera entre prevención y detección se corra: el admission control observa la misma declaración que el registro de auditoría, con la diferencia de que puede además rechazarla. Es infrecuente disponer de un punto de observación que sea también un punto de intercepción, y desaprovecharlo es el error más caro de este capítulo.

El registro de auditoría es a la vez la mejor fuente del plano de control y un objetivo del adversario. Hay que blindarlo en dos frentes. Primero, la manipulación: quien tiene acceso a la API puede alterar los registros locales, de modo que el destino tiene que ser un receptor remoto de solo anexado —el mismo razonamiento del reenvío inmediato de 5.10, agravado porque acá el atacante ataca desde la propia interfaz que genera el registro—. Segundo, un límite de implementación explotable: los cuerpos de petición que superan el tamaño máximo que el almacén de configuración admite no se persisten, lo que habilita operar con sigilo mediante peticiones sobredimensionadas. Y una advertencia inversa: el registro también ha filtrado credenciales cuando el nivel de detalle se eleva —varias vulnerabilidades documentadas por esa vía—, así que la fuente que se ingiere para detectar es también una fuente que hay que proteger como material sensible.

Efimeridad: lo que le pasa al forense#

Todo el procedimiento de 5.4 daba por sentado que el sistema comprometido sigue disponible mientras se decide qué hacer con él. Un contenedor no ofrece esa garantía: el orquestador reinicia, reprograma y reemplaza cargas de trabajo por su cuenta, sin consultar al analista y por razones que nada tienen que ver con el incidente. La consecuencia inmediata es que la recolección de evidencia tiene que ser automática y ocurrir en el momento del disparo, no cuando alguien llegue a la alerta. Es el caso más claro de todo el manual para automatizar la respuesta: no por velocidad, sino porque la ventana de recolección puede cerrarse sola.

La instrumentación existe. Herramientas de forense de pods toman una instantánea del contenedor —su configuración, las diferencias respecto de la imagen, su sistema de archivos exportado— para analizarla fuera de línea. Pero traen una omisión que en este contexto es grave: no capturan la memoria del proceso. Y la memoria es donde vive todo lo que importa. 5.5 estableció que el disco dice lo que el adversario dejó y la RAM dice lo que estaba ejecutándose; en un contenedor efímero, con sistema de archivos de solo lectura y sin persistencia, el implante que nunca tocó el disco no dejó absolutamente nada más. El argumento que en 5.5 era fuerte, acá es el único que queda. Volcar el mapa de memoria del proceso antes de que el pod muera no es un refinamiento forense: es la investigación entera.

Ese mismo hecho tiene un corolario que no es forense sino de diseño, y es probablemente la lección más accionable de la sección. Existe una herramienta ofensiva conocida que hace exactamente esto —vuelca la memoria de un proceso y la peina en busca de material de alta entropía— y encuentra con regularidad claves de API y credenciales de servicio en la RAM de procesos legítimos. La razón es estructural: un secreto inyectado como variable de entorno vive en la memoria del proceso durante toda su vida, y quien tenga privilegio de raíz en el espacio de procesos puede volcar la memoria de cualquier proceso de ese espacio —y quien lo tenga en el espacio del host, la de cualquier proceso del nodo—. De ahí la práctica correcta: traer el secreto desde el almacén en el momento de usarlo y descartarlo, en lugar de dejarlo residente durante horas. Es la contracara exacta del capítulo: la misma técnica sirve para investigar un compromiso y para consumarlo.

Matar el pod es contención y destrucción de evidencia a la vez. El reflejo ante una alerta de runtime es terminar la carga de trabajo comprometida, y la plataforma lo hace fácil —demasiado—. Pero eso elimina el proceso, su memoria y su estado en un solo movimiento, y en un contenedor sin persistencia no queda nada después. El procedimiento correcto invierte el orden y hereda las dos reglas de P5: capturar antes de aislar —como la RAM en 5.5— y contener con el alcance completo y de forma simultánea —la regla del tempo de 5.4—, porque un solo pod terminado con prisa, mientras el token robado sigue siendo válido contra la API, solo le informa al adversario que fue visto. Aislar por política de red, marcar la carga de trabajo para que el orquestador no la reemplace, capturar disco y memoria, y recién entonces terminarla.

Trampas: la red que atrapa lo que ninguna regla previó#

Los señuelos merecen un lugar propio acá por una razón práctica: en un entorno declarativo y homogéneo, desplegarlos cuesta casi nada. Un recurso trampa que ninguna aplicación legítima toca —un servicio con un nombre atractivo, desplegado como un conjunto de demonios con una instancia por nodo— alerta al ser accedido. Los canary tokens llevan la idea a las credenciales: claves de nube, direcciones, registros de nombres o documentos que solo existen para ser robados y que avisan cuando alguien los usa.

Su valor es doble y complementa exactamente los huecos de las secciones anteriores. Primero, tienen tasa de falsos positivos nula por construcción: nada legítimo los toca, así que no requieren línea base, ni ajuste, ni mantenimiento de excepciones. Segundo, y más importante, detectan en la fase de descubrimiento —el momento en que el adversario está averiguando qué hay, que 5.9 identificaba como la señal más temprana y barata— y lo hacen sin depender de haber anticipado la técnica. Todo el resto de este capítulo detecta comportamientos que alguien previó y escribió como regla; el señuelo detecta la curiosidad, que es previa a cualquier técnica concreta. Es la red que atrapa lo que el catálogo no vio, y por eso pertenece al programa aunque no sea glamorosa.

flowchart TD
  A["Intrusión cloud-native"]
  A --> DP["PLANO DE DATOS\n(el workload en el nodo)"]
  A --> CP["PLANO DE CONTROL\n(peticiones al API server)\n⚠ ningún sensor de host lo ve"]
  DP --> EB["IDS eBPF (Falco/Tracee)\nshell en contenedor · execve/open anómalo\ncon contexto de namespace"]
  CP --> AL["Audit log → receptor remoto append-only\nSA que recorre el árbol · exec/attach · token desde fuera"]
  CP --> AC["Admission control\n= el MISMO manifiesto, pero se puede rechazar"]
  HP["Señuelos y canary tokens\n(detectan el descubrimiento,\nsin anticipar la técnica)"] --> X
  EB & AL & AC --> X["Correlación en el SIEM\n= una historia, no alertas sueltas"]
  X --> F["Recolección AUTOMÁTICA en el disparo\n(el pod puede desaparecer solo)"]
  F --> M["Disco + MEMORIA\n(sin persistencia, la RAM es todo lo que hay)"]
  M --> C["Contener con alcance completo\nrevocar el token · recién entonces terminar"]

Postura, ordenada por retorno real#

  1. Ingerir el registro de auditoría del API server y enviarlo fuera del clúster, de solo anexado. Es la brecha de cobertura más frecuente y la que deja invisible una cadena de ataque entera; sin ella, media superficie no tiene telemetría.
  2. Desplegar un IDS de runtime por eBPF y empezar por las reglas de altísima fidelidad —intérprete de comandos en un contenedor, escritura donde debería haber solo lectura, montajes sensibles—, que rinden desde el primer día sin sintonización.
  3. Explotar que el ataque se declara antes de ejecutarse: alertar sobre las declaraciones precursoras de escape y, donde sea posible, rechazarlas con admission control, que observa lo mismo y además interviene.
  4. Automatizar la recolección de evidencia en el momento del disparo, con memoria incluida. La ventana se cierra sola y el orquestador no espera a nadie.
  5. Validar el catálogo de reglas con pruebas dirigidas. Las reglas heredadas de la comunidad son código con errores; medir que disparan es la aplicación directa de 5.8.
  6. Sacar los secretos de las variables de entorno, para que un volcado de memoria deje de ser una cosecha de credenciales.
  7. Sembrar señuelos y canary tokens: costo casi nulo, cero falsos positivos y cobertura de lo que ninguna regla anticipó.
  8. Tratar al propio agente de seguridad como activo crítico, porque su privilegio es exactamente el que se necesita para escapar.

Cierre de la Parte 5#

Con este capítulo se cierra el recorrido azul y también el último hilo pendiente del bloque rojo. Vale recogerlo entero, porque los once capítulos sostienen un solo argumento. 5.1 planteó que la defensa es un programa de funciones que interoperan y que la detección madura apunta al comportamiento y no al indicador atómico. 5.2 puso la capa de datos bajo esa afirmación: no se detecta lo que no se registra. 5.3, 5.6, 5.7, 5.9 y 5.10 recorrieron las superficies —identidad y correo, movimiento lateral, canal de mando, fuga de datos, persistencia— y en cada una reapareció la misma estructura: el adversario controla cómo se ven las cosas y no controla lo que su operación tiene que hacer para funcionar. 5.4 y 5.5 dieron la respuesta y la evidencia, con las dos reglas que atraviesan todo: capturar antes de aislar, contener con el alcance completo. 5.8 agregó el movimiento que separa un programa real de un inventario de productos: medir empíricamente qué detecta el sensor propio, porque una regla no está terminada hasta que se verificó que dispara.

Este último capítulo cierra con la variante más favorable de ese argumento. En un entorno declarativo, de propósito único e inmutable, la asimetría que hace cara a la defensa —el defensor tiene que saber qué es normal y el adversario no— se reduce hasta casi desaparecer, porque el sistema declara lo que es normal antes de ejecutarlo. La detección deja de ser una reconstrucción y pasa a ser una comparación. Ese es el mejor resumen disponible de lo que P5 vino sosteniendo: la ventaja defensiva no se compra, se construye eligiendo dónde observar.

Referencias#