Un host de Docker cuya API está expuesta en internet sin autenticación no ofrece simplemente una función cómoda de administración remota. Está ofreciendo una vía remota hacia la máquina que ejecuta los contenedores. La campaña CARBONATO, reportada el 30 de septiembre, vuelve difícil ignorar esa diferencia: los atacantes utilizan APIs remotas de Docker expuestas para crear contenedores privilegiados, establecer persistencia, robar credenciales y buscar más hosts Docker.

Ilustración editorial de un host Docker expuesto, con una ruta de acceso desde Internet hacia el servidor y el plano de control de contenedores.

El incidente merece atención porque, en esencia, no es una historia sobre una nueva vulnerabilidad de Docker. Es la historia de una interfaz administrativa colocada en una red no confiable sin una barrera de autenticación. El malware incorpora una carga moderna, incluido un marco de agentes de IA de código abierto reutilizado, pero la condición que permite el ataque es más antigua y sencilla: cualquiera que pueda alcanzar el daemon puede pedirle que realice operaciones con la autoridad del host.

Para los equipos que ejecutan Docker en servidores cloud, máquinas de compilación, hosts de desarrollo, servicios autogestionados o sistemas periféricos, la respuesta adecuada es evaluar la exposición y el posible compromiso. Cierren la vía sin autenticación, determinen si el host fue utilizado, roten todo lo que pudiera leer y revisen después los sistemas adyacentes. Reinstalar un contenedor o cambiar una etiqueta de imagen no basta si el host subyacente o sus credenciales ya podrían estar bajo control ajeno.

Qué dice realmente la información sobre CARBONATO

El aviso de la Agencia de Ciberseguridad de Singapur publicado el 30 de septiembre afirma que los investigadores identificaron una campaña de botnet dirigida contra hosts Docker cuyas APIs remotas sin autenticación estaban expuestas en internet, normalmente en el puerto TCP 2375. El aviso describe una campaña que utiliza funciones legítimas de Docker para crear un contenedor privilegiado con acceso al sistema de archivos, los procesos y la red del host.

La secuencia importa. El atacante no necesita explotar un fallo de seguridad de memoria en Docker Engine si el daemon acepta solicitudes administrativas de una parte no confiable. Una solicitud normal para un administrador —crear un contenedor, montar una ruta, iniciar un proceso o conectar una red— puede convertirse en control del host cuando quien la envía no está autenticado y el daemon se ejecuta con privilegios elevados.

El aviso de Singapur indica que la campaña puede establecer acceso remoto persistente, robar credenciales y otra información sensible, y escanear redes conectadas en busca de hosts Docker expuestos adicionales. No afirma que todos los hosts expuestos hayan sido comprometidos, ni ofrece un indicador universal que por sí solo pueda confirmar o descartar un incidente. Esos límites son importantes. El aviso es un motivo para investigar la exposición y los registros, no una autorización para etiquetar como infectada toda instalación de Docker.

Una nota de investigación de Cloud Security Alliance aporta contexto sobre la carga. Describe CARBONATO como una botnet autorreplicante que instala un marco de agentes de IA de código abierto sin modificar, Hermes Agent, y cambia la configuración de personalidad del marco para que sirva a los objetivos de los operadores. La nota de investigación señala que los hosts infectados escanean rangos de red vecinos en busca de otros daemons de Docker.

La parte inusual es la elección de la carga. Para los defensores, lo importante sigue siendo la vía de acceso. La presencia de un marco de IA puede atraer la atención, pero un atacante no necesita un agente de IA para convertir un daemon de Docker expuesto en un incidente grave. La misma exposición administrativa podría servir para robar credenciales, minar criptomonedas, ejecutar acciones destructivas, actuar como proxy, moverse lateralmente o desplegar una puerta trasera convencional.

Por qué el puerto 2375 exige una respuesta precisa

La documentación de Docker distingue entre su socket local habitual y las conexiones de red remotas. De forma predeterminada, Docker utiliza en Linux y macOS un socket Unix que no está conectado a la red. La administración remota puede realizarse mediante SSH o mediante un socket TCP protegido con TLS y autenticación del cliente.

La documentación de Docker también identifica la división convencional de puertos: el TCP 2375 se utiliza normalmente para conexiones inseguras sin TLS, mientras que el TCP 2376 se asocia convencionalmente con TLS. El número, por sí solo, no demuestra un compromiso, y utilizar otro puerto no vuelve segura una API sin autenticación. El puerto 2375 es simplemente una señal útil para la detección porque suele indicar que un daemon Docker fue configurado para permitir acceso remoto sin cifrado.

La pregunta crítica no es «¿Está abierto el puerto 2375?» de forma aislada. Es:

  • ¿Qué proceso está escuchando?
  • ¿El listener es accesible desde internet, desde una red corporativa amplia o únicamente desde un segmento de administración restringido?
  • ¿Exige autenticación y autoriza correctamente al cliente?
  • ¿Qué daemon Docker, cuenta, host y carga de trabajo se encuentran detrás?
  • ¿Hay registros de solicitudes que el propietario no realizó?

Un servicio expuesto a internet puede ser peligroso incluso cuando no es accesible de forma global. Un daemon expuesto a una red interna plana puede seguir estando disponible para una estación de trabajo comprometida, un dispositivo de un contratista, una cuenta de desarrollo u otra carga que nunca debería tener control administrativo sobre el host. «Solo está abierto dentro de la VPC» es una afirmación de red, no un modelo de autorización.

El problema de fondo: el acceso a Docker es acceso al host

Los contenedores son límites de aislamiento útiles, pero el acceso al daemon de Docker es un privilegio de administración. Docker advierte que cambiar la vinculación del daemon a un socket TCP, o conceder acceso al socket Unix mediante el grupo docker, puede permitir que un usuario obtenga acceso equivalente a root en el host. Esta advertencia es fácil de pasar por alto cuando un equipo está solucionando problemas de un sistema de compilación o intenta facilitar el desarrollo remoto.

Un contenedor creado con privilegios elevados puede ver o modificar recursos del host. Incluso sin reproducir una secuencia de ataque, la implicación defensiva es directa: traten las credenciales del daemon Docker y el acceso a su socket como credenciales de root. Pertenecen a la misma categoría de riesgo que las claves de administrador cloud, las interfaces de gestión de hipervisores y el acceso al plano de control de Kubernetes.

Por eso eliminar un contenedor sospechoso es, por sí solo, una acción de contención débil. Si un atacante tuvo acceso al nivel del daemon, pudo leer variables de entorno, montar directorios del host, inspeccionar otros contenedores, copiar archivos de configuración, modificar mecanismos de inicio, crear cuentas adicionales o recolectar credenciales del host. El contenedor visible puede ser solo un artefacto de un compromiso más amplio.

El mismo principio se aplica a los runners de CI. Un runner de compilación con acceso a un socket Docker privilegiado puede exponer código fuente, material de firma, credenciales de paquetes, tokens cloud y permisos de despliegue. Un portátil de desarrollador con un socket Docker montado puede exponer archivos locales y el entorno del host. Una API remota introducida por comodidad puede, por tanto, conectar un flujo de trabajo de contenedores con las identidades y la infraestructura que lo rodean.

Qué deben hacer primero los administradores

La primera respuesta debe reducir el alcance del atacante sin destruir las pruebas.

1. Identificar cada daemon Docker con exposición de red

Comiencen con un inventario autorizado, no con la memoria del equipo. Revisen los grupos de seguridad cloud, los firewalls de los hosts, los balanceadores, las rutas VPN, los registros de descubrimiento de servicios, la configuración de los hosts de contenedores, las unidades de systemd, los archivos de configuración del daemon, las plantillas de orquestación y los repositorios de infraestructura como código.

Busquen listeners del daemon Docker en los puertos TCP 2375 y 2376, pero también puertos personalizados y vinculaciones como un daemon que escuche en todas las interfaces. Revisen tanto los entornos de producción como los que no lo son. Los hosts de desarrollo suelen estar más expuestos, menos supervisados y conectados a redes que contienen credenciales valiosas.

La Guía de reducción de exposición en internet de CISA recomienda obtener visibilidad de los activos expuestos a internet y reducir la exposición innecesaria. El mismo enfoque se aplica a la exposición interna: establezcan qué es accesible, desde dónde y por qué razón empresarial. Un activo ausente del inventario no puede parchearse, supervisarse ni investigarse de forma fiable.

Si un daemon sin autenticación está expuesto, restrinjan el acceso inmediatamente en la capa de red mientras conservan los registros y las trazas de cambios. El objetivo de emergencia es detener nuevas conexiones sin autenticación. No supongan que un cambio de firewall demuestra que el host está limpio; solo cambia quién puede alcanzarlo.

2. Eliminar el acceso remoto sin protección

La guía oficial de Docker para proteger el socket del daemon recomienda utilizar SSH o TLS para proteger el acceso remoto. SSH puede ser una opción práctica para los flujos de trabajo de los operadores porque reenvía las solicitudes al socket Unix remoto y aprovecha el modelo existente de autenticación y autorización del host.

Cuando el acceso TCP sea realmente necesario, utilicen TLS con autenticación mutua y una autoridad certificadora controlada, protejan las claves privadas, restrinjan las redes de origen y registren la actividad administrativa. Un servicio cifrado con TLS pero sin autenticación sigue teniendo un problema de autorización. El cifrado protege el tráfico frente a la observación y la manipulación; no decide si un cliente debe poder crear contenedores privilegiados.

Prefieran una ruta privada de administración en lugar de un listener público. Apliquen el mínimo privilegio a las identidades que puedan administrar el daemon, separen la administración humana de la automatización y eviten distribuir un certificado de cliente reutilizable y demasiado amplio a trabajos de compilación o a varios equipos. Un certificado de cliente que concede acceso Docker sin restricciones debe tratarse como una credencial de root del host.

No resuelvan una exposición cambiando únicamente el número de puerto. Los grupos de seguridad, los firewalls del host, el enrutamiento, la autenticación y la autorización deben coincidir con el límite de administración previsto.

3. Conservar y revisar las pruebas

En un host potencialmente expuesto, conserven los registros relevantes del sistema, firewall, cloud, Docker, orquestación e identidad antes de rotarlo o reconstruirlo. Establezcan el periodo durante el cual el daemon fue accesible y compárenlo con los informes de la campaña y con su propia telemetría.

Entre las preguntas de revisión útiles están las siguientes:

  • ¿Hubo solicitudes inesperadas a endpoints de la API de Docker?
  • ¿Se crearon, iniciaron, detuvieron o eliminaron contenedores fuera de las ventanas normales de despliegue?
  • ¿Apareció alguna imagen, registro, red, volumen o secreto nuevo?
  • ¿Se montaron rutas del host en contenedores de forma inesperada?
  • ¿Se ejecutó algún contenedor con privilegios elevados, red del host o acceso a directorios sensibles?
  • ¿Se crearon en el host procesos, usuarios, tareas programadas, servicios, claves SSH o entradas de inicio nuevas?
  • ¿El host realizó conexiones salientes inusuales, especialmente hacia infraestructura de mando y control o registros desconocidos?
  • ¿Mostraron otros hosts de la misma red intentos de conexión relacionados con Docker poco después?

El objetivo no es buscar un único nombre de archivo mágico. Los atacantes pueden eliminar contenedores, cambiar el nombre de procesos, utilizar herramientas legítimas o desplegar otra carga. Correlacionen la actividad de la API con la ejecución de procesos, los flujos de red, el acceso a registros, los eventos de auditoría cloud y los registros del proveedor de identidad.

Si el host contiene cargas sensibles o los registros no permiten establecer qué ocurrió, aíslenlo y sigan el proceso de respuesta a incidentes de la organización. Reconstruyan desde una imagen confiable cuando la integridad del host esté en duda. Una reconstrucción es más creíble cuando también se revisan las credenciales, la configuración y los artefactos de despliegue, en vez de copiarlos íntegramente desde el sistema potencialmente comprometido.

4. Rotar los secretos expuestos según su autoridad

Supongan que pudieron quedar expuestos los secretos legibles por el daemon Docker, el host, los volúmenes montados, las variables de entorno, las capas de imagen o los procesos en ejecución. Prioricen las credenciales por lo que pueden hacer, no por el lugar donde estaban almacenadas.

Esto puede incluir claves de acceso cloud, tokens de CI, tokens de control de código fuente, credenciales de registros, contraseñas de bases de datos, claves SSH, claves de firma, secretos de webhooks, tokens de cuentas de servicio y credenciales incorporadas en archivos de despliegue. Revoquen o roten esos elementos desde una ruta administrativa confiable. Comprueben si las credenciales nuevas se utilizaron de forma inesperada después de su emisión.

Rotar sin revocar es incompleto si la credencial antigua sigue siendo válida. Rotar sin revisar los registros no permite saber si un atacante ya utilizó el secreto para acceder a otro servicio. Rotar sin conocer las dependencias puede interrumpir producción, por lo que la operación debe coordinarse, pero la incomodidad operativa no es una razón para mantener activas credenciales de alto valor después de una exposición creíble.

Revisen también los secretos que no estuvieran almacenados directamente en el host pero fueran accesibles a través de su identidad. Un rol de instancia cloud, una identidad de carga de trabajo o una cuenta de servicio de CI comprometidos pueden ampliar el incidente mucho más allá de un único servidor Docker.

Cómo es una arquitectura segura

Una instalación de Docker defendible suele tener una ruta administrativa estrecha y una razón explícita para cada excepción.

Para la administración local, mantengan protegido el socket Unix predeterminado mediante los controles de acceso del host y limiten la pertenencia al grupo docker. Pertenecer a ese grupo no es una simple comodidad: puede proporcionar un control amplio sobre el daemon y, por tanto, sobre el host.

Para la administración remota, utilicen SSH o TLS con autenticación mutua, limiten las direcciones de origen y coloquen el servicio detrás de una red de gestión o una VPN cuando corresponda. Mantengan los registros fuera del host para que un atacante no pueda borrar la única copia. Supervisionen la emisión de certificados, el uso de claves y los cambios en la configuración del daemon.

En CI, eviten entregar a un trabajo de compilación no confiable un socket del host con privilegios. Consideren modos rootless, runners aislados, trabajadores de corta duración, identidades separadas para compilación y despliegue y APIs de alcance limitado. Si una compilación necesita realmente operaciones privilegiadas, traten el runner como un sistema administrativo de alto riesgo y aíslenlo en consecuencia.

En entornos cloud, incluyan los listeners de Docker en la gestión de la superficie de ataque y en la detección de desviaciones de configuración. Una plantilla segura puede deshacerse después mediante un script de lanzamiento, una configuración del daemon incluida en una imagen, un comando de diagnóstico o una excepción temporal del firewall que termina siendo permanente.

Para los desarrolladores, documenten el flujo de trabajo remoto aprobado. Los equipos suelen crear listeners inseguros porque la vía segura no está clara o resulta incómoda. Un contexto SSH compatible, un entorno de desarrollo gestionado o un servicio de compilación bien diseñado elimina la presión de exponer directamente un daemon.

Cómo distinguir exposición de compromiso confirmado

Un listener Docker público o ampliamente accesible dentro de la organización es un hallazgo grave, pero no demuestra automáticamente que un atacante lo haya utilizado. Mantengan separados estos tres estados en los registros del incidente:

  1. Exposición confirmada: el daemon aceptaba o podía aceptar conexiones desde una red no confiable.
  2. Actividad sospechosa identificada: los registros o la telemetría del host muestran solicitudes, procesos, actividad de red o cambios de configuración que no se explican por trabajo autorizado.
  3. Compromiso confirmado: los investigadores tienen pruebas suficientes de que una parte no autorizada obtuvo control o accedió a datos.

Esta distinción mejora las decisiones. La exposición confirmada debe activar el cierre inmediato y una revisión basada en el riesgo. La actividad sospechosa identificada debe activar la contención y la respuesta a incidentes. El compromiso confirmado debe activar la delimitación completa, la revocación de credenciales, la recuperación, la evaluación de notificaciones y las lecciones aprendidas.

También evita dos errores frecuentes. El primero es la complacencia: «No vimos un contenedor malicioso, así que la exposición no tenía consecuencias». El segundo es la exageración: «El puerto 2375 estaba abierto, por lo tanto todo el entorno fue vulnerado». Un buen informe de seguridad puede ser urgente sin fingir que las pruebas permiten saber más de lo que realmente se sabe.

El componente de IA es secundario, aunque también resulta útil

El uso que hace CARBONATO de un marco de agentes de IA es una señal sobre cómo los atacantes pueden empaquetar la automatización, no una razón para considerar malicioso cualquier componente de IA. El marco descrito por Cloud Security Alliance es de código abierto y puede tener usos legítimos. Su reutilización en una botnet ilustra un patrón conocido de seguridad: el software legítimo pasa a formar parte de un ataque cuando un adversario controla el entorno de ejecución y la configuración que lo rodean.

Por tanto, los defensores deben incorporar a la investigación el software instalado, los archivos de configuración, la actividad programada, los destinos salientes y las credenciales a las que se accedió. Buscar únicamente el nombre de un producto puede dejar fuera un despliegue modificado o una carga completamente distinta. A la inversa, bloquear el nombre de un marco legítimo sin corregir la exposición de Docker deja abierta la vía de acceso original.

La lección más amplia se refiere a los límites de la automatización. Un marco de IA ejecutándose en un host comprometido puede hacer más flexible la ejecución de tareas, pero no crea la autoridad inicial. Esa autoridad procedía del daemon Docker. La autenticación sólida, la segmentación de red, la integridad del host, la higiene de credenciales y unos registros útiles siguen siendo los controles importantes.

Lista práctica para la próxima revisión

Los equipos pueden convertir este incidente en una revisión de controles repetible:

  • Inventariar todos los daemons Docker y las redes que pueden alcanzarlos.
  • Confirmar que ninguna API Docker sin autenticación está expuesta a internet o a una red interna no confiable.
  • Buscar el TCP 2375 y listeners personalizados del daemon, no solo los nombres de servicio esperados.
  • Sustituir la administración TCP improvisada por SSH o TLS con autenticación mutua configurado correctamente.
  • Restringir el acceso al socket Docker y revisar la pertenencia al grupo docker.
  • Separar los runners de CI de las redes y credenciales de producción sensibles.
  • Centralizar los registros de Docker, del host, del firewall, de la nube, de identidad y de los registros de imágenes.
  • Revisar la creación inesperada de contenedores, los ajustes privilegiados, los montajes del host, las imágenes nuevas y las conexiones salientes.
  • Rotar las credenciales que pudieran ser legibles desde los hosts o las cargas afectadas.
  • Reconstruir los hosts cuando su integridad no pueda establecerse desde medios confiables.
  • Incorporar la exposición del daemon y las desviaciones de configuración a las comprobaciones de seguridad recurrentes.
  • Documentar un flujo de administración remota aprobado para que los ingenieros no creen listeners de emergencia.

CARBONATO recuerda oportunamente que el plano de control de una plataforma de contenedores es un activo crítico por sí mismo. La acción defensiva decisiva no consiste en especular sobre la novedad de la carga. Consiste en verificar quién puede alcanzar el daemon, qué puede hacer el daemon, qué ha hecho recientemente y qué identidades quedarían expuestas si el host estuviera comprometido. Cuando esas preguntas se convierten en una rutina, el riesgo resulta más fácil de gestionar sin pánico ni deseos infundados.

Fuentes