1 puntos por GN⁺ 2025-12-19 | 1 comentarios | Compartir por WhatsApp
  • Se detectó un uso anormal de CPU en un servidor de Hetzner operado de forma personal y, al investigarlo, se descubrió que estaba ejecutándose un programa de minería de criptomonedas Monero (xmrig)
  • La causa fue que el contenedor de la herramienta de analítica Umami fue comprometido, incluyendo una vulnerabilidad de ejecución remota de código en Next.js (CVE-2025-66478)
  • Afortunadamente, como ese contenedor se ejecutaba con un usuario no root y no tenía montajes del host ni escalamiento de privilegios, la intrusión quedó limitada al interior del contenedor
  • El atacante aprovechó la deserialización insegura de los Server Components de Next.js para ejecutar una carga maliciosa e instalar el minero
  • Este caso muestra la importancia de la gestión de dependencias y de la configuración de seguridad de contenedores, y el autor reforzó sus medidas de seguridad activando el firewall, endureciendo SSH y aplicando actualizaciones periódicas

El incidente y la respuesta inicial

  • Se recibió de Hetzner un correo de advertencia indicando que el servidor había escaneado redes externas
    • Incluía el aviso de que el servidor podía ser bloqueado si no se actuaba en un plazo de 4 horas
  • Al revisar por SSH, se encontró un proceso usando 819% de CPU en la ruta /tmp/.XIN-unix/javae, junto con varios procesos xmrig
  • Se confirmó que la minería de criptomonedas llevaba aproximadamente 10 días en marcha

Investigación de la vía de intrusión

  • Todos los procesos maliciosos se estaban ejecutando con el usuario UID 1001, lo que coincidía con el contenedor de Umami
  • Se encontró el binario del minero en el directorio /app/node_modules/next/dist/server/lib/xmrig-6.24.0/
  • El comando de ejecución incluía la dirección del pool de minería auto.c3pool.org:443 y una clave de usuario

La vulnerabilidad de Next.js y el método de ataque

  • La causa fue la vulnerabilidad de deserialización de React Server Components en Next.js (CVE-2025-66478)
    • Si un atacante enviaba una solicitud HTTP manipulada, podía ejecutar código arbitrario en el servidor
    • Como resultado, era posible instalar y ejecutar un minero de criptomonedas
  • El autor pensaba que “no usaba Next.js directamente”, pero más tarde se dio cuenta de que Umami está basado en Next.js

Verificación del aislamiento del contenedor

  • Se confirmó que /tmp/.XIN-unix/javae no existía en el sistema de archivos del host
    • Solo era un efecto de que la salida de docker ps muestra procesos del contenedor; en la práctica, el aislamiento se mantenía
  • Resultado de docker inspect
    • Usuario: nextjs
    • Privileged: false
    • Mounts: ninguno
  • Por lo tanto, el malware no pudo acceder al host, registrar tareas cron, crear servicios del sistema ni instalar rootkits

Recuperación y refuerzo de seguridad

  • Tras detener y eliminar el contenedor infectado de Umami, el uso de CPU volvió a la normalidad
  • Se activó el firewall UFW para permitir solo SSH, HTTP y HTTPS
  • Después de reportar a Hetzner el resultado de la investigación, el ticket se cerró en menos de 1 hora

Lecciones y mejoras

  • Decir “yo no uso X” no incluye necesariamente las dependencias
    • Hay que revisar con qué stack tecnológico están construidas las herramientas que se usan
  • Se demostró la eficacia del aislamiento de contenedores
    • Ejecutar con usuario no root, en modo no privilegiado y sin volúmenes innecesarios evitó que el daño se propagara
  • Es necesaria una defensa en profundidad (Defense in Depth)
    • Firewall, fail2ban, monitoreo y actualizaciones periódicas son esenciales
  • Se enfatiza la importancia de escribir el Dockerfile directamente y de minimizar los privilegios del contenedor

Medidas tomadas después del incidente

  • Se volvió a desplegar Umami con la versión más reciente y se auditaron todos los contenedores de terceros
    • Se revisaron el usuario de ejecución, los montajes, el momento de actualización y la necesidad de cada uno
  • Se cambió a autenticación con clave SSH, se deshabilitó el inicio de sesión por contraseña y se configuró fail2ban
  • Se reforzó el monitoreo con Grafana y Node Exporter y se aplicaron de inmediato las actualizaciones de seguridad

Conclusión

  • Aunque la vulnerabilidad de Next.js en Umami permitió que se usara el sistema para minar Monero durante 10 días, el aislamiento del contenedor y la ejecución sin root limitaron el impacto
  • A través de esta experiencia, el autor internalizó la importancia de conocer las dependencias, configurar la seguridad y gestionar las actualizaciones
  • El incidente se contuvo en unas 2 horas y quedó como un caso real que validó la eficacia práctica de la seguridad en contenedores

1 comentarios

 
GN⁺ 2025-12-19
Comentarios de Hacker News
  • Antes recomendaba UFW, pero ahora recomiendo firewalld
    UFW se vuelve difícil de administrar con el tiempo, mientras que firewalld es mucho más estable gracias a su configuración basada en XML
    Con el comando firewall-cmd se puede configurar SSH, HTTPS, el puerto 80, etc., y conviene usar el backend de nftables
    En el caso de Docker, a menudo termina abriendo puertos saltándose las reglas del firewall, así que es más seguro configurar StrictForwardPorts=yes en /etc/firewalld/firewalld.conf

    • En lugar de abrir puertos como 8080:8080, es mejor hacer bind a una IP privada como 192.168.0.1:8080:8080
      Yo corro Docker en una VM 10.0.10.11, accesible solo por WireGuard, y me resultó práctico poner Caddy como proxy inverso
    • Recomiendo instalar Podman en lugar de Docker. En Docker es común el problema de saltarse el firewall
    • Sin importar qué frontend de netfilter uses, no sirve de nada si no hay restricciones de conexiones salientes
      El malware intentará conectarse a un pool de minería externo o a un servidor C2, así que hay que bloquear el acceso a la red de binarios no autorizados
      También sirve quitar permisos de ejecución de /tmp, /var/tmp y /dev/shm
    • Hetzner ofrece un servicio de firewall externo gratuito, así que puede usarse como primera línea de defensa
    • Personalmente, siento que con nftables.conf por sí solo ya queda todo suficientemente simple y claro
      iptables ya está deprecado, así que no hace falta una capa extra como firewalld
  • Esto parece estar relacionado con “React2Shell CVE-2025-55182
    Es raro que una vulnerabilidad que lleva más de un año afectando a sistemas casi no haya recibido atención
    Si desplegaste una web app con Next.js en los últimos 12 meses, es muy probable que ya forme parte de una botnet
    Frustra que la industria solo dé consejos del tipo “usa Docker” o “enciende el firewall”
    Últimamente me siento tan escéptico con el ecosistema frontend que estoy pensando en mover mi carrera hacia C++

    • El ritmo de recambio tecnológico del frontend es mucho más relajado que antes
      Hoy la combinación Next.js, React, Tailwind y Postgres lleva 5 años consolidada casi como estándar
      Comparado con la época de explosión de frameworks de finales de los 2000 y principios de los 2010, ahora es bastante estable
      Si no te gustan las modas y el cambio, el desarrollo de IA cambia mucho más rápido
    • Se pueden hacer web apps perfectamente sin usar frameworks JS modernos
      En backend puedes usar un stack tecnológico sólido como .NET, Java o Go, y elegir el frontend con más libertad
      Así reduces CVEs y también el cansancio tecnológico
    • Mi instancia de Pangolin también fue comprometida por esta vulnerabilidad
      Discusión relacionada en GitHub
    • Yo también desplegué unos 100 frontends en Next.js, y por suerte no me afectó porque no usaba Server Components
  • Si limitas el uso de CPU de un contenedor Docker con --cpus="0.5", un servicio con fallas o un minero no afecta a todo el sistema

    • Correr el contenedor en modo read-only también puede reducir más la superficie de ataque
    • Pero si el límite de CPU es demasiado bajo, la intrusión puede pasar más desapercibida y demorar la detección
    • Hay que conocer bien el perfil de rendimiento de la app. Si luego llega tráfico en ráfagas, podrías terminar aplicando throttling sin querer
    • También conviene configurar límites soft/hard de memoria
  • Operar un servidor sin firewall es una decisión bastante audaz
    Si además usas el firewall externo de Hetzner, tienes una capa de defensa extra por si cometes un error
    Yo permito SSH solo desde la IP de mi casa, y cuando lo necesito desde fuera, lo habilito temporalmente desde el sitio web de Hetzner

    • En la mayoría de los casos, el firewall no ayuda mucho
      Lo realmente importante es no ejecutar software con vulnerabilidades RCE
      Que Docker pareciera haber sido el salvador fue, en realidad, solo cuestión de suerte
    • Si es un servicio web público, el firewall no ayuda demasiado
      En cambio, se puede usar un bastion host y controlar entrada y salida con un proxy HTTP, pero configurarlo es complejo
    • En 30 años administrando Linux, la única vez que me hackearon fue cuando dejé abiertos puertos bien conocidos
      Usar puertos no estándar resultó sorprendentemente efectivo
    • Dejar activada la autenticación por contraseña es riesgoso. Personalmente, no creo que fail2ban sea imprescindible
    • Intento evadir escáneres de puertos cambiando el puerto de SSH a uno aleatorio
      No sé qué tan efectivo sea, pero se siente como una especie de paraguas psicológico
  • Me preguntaba si al correr un contenedor Docker como root también se podía atacar al host

    • Docker no es un límite de seguridad. Solo ofrece aislamiento a nivel de proceso
      Si quieres correr código no confiable, debes usar una VM (KVM/QEMU) o tecnologías como gVisor(https://gvisor.dev/) y Firecracker(https://firecracker-microvm.github.io/)
      Docker debe entenderse más como un entorno de ejecución aislado que como un sandbox
    • Un atacante puede usar CPU incluso dentro del contenedor para minar Monero
      La configuración por defecto de Docker no limita RAM, CPU ni uso de disco, así que también es vulnerable a ataques DoS
      Además, muchas guías recomiendan opciones riesgosas como --privileged o CAP_SYS_PTRACE
    • En modo privileged, se puede acceder al sistema de archivos root del host a través del socket de Docker
      También es posible levantar un contenedor nuevo y escalar a privilegios de root
    • Hay que activar user namespace para tener un límite de seguridad real
      Docker todavía no lo trae como valor por defecto, así que si no lo configuras, el riesgo de escape es alto
      En el pasado, la mayoría de los escapes de contenedores podrían haberse evitado con user namespace
    • Aunque existen escapes de contenedores, la mayoría son simples ataques automatizados de minería
      Si el servidor no maneja datos sensibles, muchas veces basta con limpiar el contenedor
  • Para reducir la superficie de ataque, no deberías exponer al exterior servicios que no necesitan ser públicos
    Por ejemplo, se puede hacer que una herramienta de analítica sea accesible solo mediante WireGuard o un proxy SOCKS por SSH

  • Yo también sufrí una infección con un minero de Monero en un servidor de Hetzner
    Por suerte ocurrió solo dentro de un contenedor LXC de Incus, y como la prioridad de CPU era baja, no me di cuenta
    Se había agregado una clave SSH a la cuenta root y se había instalado un agente de administración remota
    Al final descarté el contenedor, pero me dejó varias lecciones

    • Hay que asumir que el sistema algún día será comprometido y configurar aislamiento y límites de recursos
    • Si mantienes snapshots de ZFS y backups de forma periódica, la recuperación es sencilla
    • Lo ideal es desechar un sistema comprometido, pero según la situación también se puede hacer rollback y endurecerlo después
    • El minero estaba mal configurado y por eso se notó, pero si la intrusión hubiera sido silenciosa, quizá nunca me habría enterado
    • Ocurrió en el contenedor donde tenía instalado Umami
  • El artículo incluía contenido de alucinaciones de IA no corregido por una persona
    Repite que era una vulnerabilidad relacionada con Puppeteer, pero eso no es cierto

    • En el primer párrafo del texto original se indicaba claramente que era una transcripción de una sesión de Claude
  • Últimamente están instalando mineros de Monero por todos lados explotando una vulnerabilidad de React 19
    A mí también me pasó lo mismo

    • Este tipo de malware de minería suele ser muy visible y hace poco daño, así que hasta resulta útil
      Funciona como una especie de bug bounty automático, porque te avisa que tienes una vulnerabilidad
      Si tienes buen monitoreo de red o procesos, se detecta fácilmente
    • Un servidor de Umami en Oracle Cloud se infectó y reinicié el servidor desde cero
      Gracias a eso tuve una buena oportunidad para mejorar mi sistema de backups
  • Casos como este me hacen pensar que hice bien en no seguir administrando VPS por mi cuenta
    Ya lo intenté antes, pero siento que estoy en un nivel de administrador promedio y mantener la seguridad se me hace difícil
    Por eso ahora prefiero dejarlo en manos de expertos y pagar el costo, porque me da mucha más tranquilidad