Problema

En entornos de virtualización donde la interfaz web de gestión está accesible desde Internet, es frecuente observar apagados masivos de máquinas virtuales, archivos de respaldo renombrados o cifrados y la aparición de indicadores de compromiso como README_DESTROY.txt. Estos síntomas apuntan a una vulnerabilidad que permite eludir la autenticación del panel de control y ejecutar acciones arbitrarias sobre el host. El patrón se repite en cualquier plataforma que exponga directamente su puerto de administración (por ejemplo, 8006 en Proxmox) sin capas de protección adicionales.

Causa

Los vectores de ataque más habituales combinan dos factores:

  1. Exposición del puerto de gestión – Cuando el puerto 8006 está abierto al exterior, cualquier cliente puede alcanzar la API de login. Sin una VPN, lista blanca de IPs o 2FA, el atacante tiene una superficie de ataque amplia.
  2. Vulnerabilidad de bypass de autenticación – En versiones de Proxmox VE 7.x y en algunas compilaciones tempranas de 8.0, el módulo libpve-access-control permite enviar un valor arbitrario en el parámetro tfa-challenge y saltarse la verificación de contraseña. La falla, catalogada como CVE‑2023‑54391, se explota mediante una petición POST a /api2/json/access/ticket. Una vez dentro, el atacante obtiene un ticket válido y puede ejecutar cualquier operación soportada por la API, incluida la parada de VMs y la manipulación de backups.

Otros problemas menores, como el XXE en libpve-storage-perl (CVE‑2026‑51080), pueden revelar rutas de archivo y facilitar la fase de reconocimiento, pero el daño crítico proviene del bypass de autenticación.

Solución

El enfoque se divide en tres capas:

  1. Corte de superficie

    • Bloquear el acceso directo al puerto 8006 desde Internet. Utilizar una VPN, firewall de capa 3 o una red de gestión aislada.
    • Si el puerto debe permanecer accesible, limitarlo a rangos de IP confiables mediante reglas iptables o nftables.
  2. Fortalecimiento de la autenticación

    • Habilitar 2FA para todas las cuentas de administración (root@pam y usuarios con privilegios).
    • Desactivar la autenticación basada en tokens API que no requieran 2FA, o regenerar los tokens después de la actualización.
  3. Actualización y parcheo

    • Actualizar libpve-access-control a una versión ≥ 8.0.4 o a la última rama de 7.x que incluya el parche.
    • Verificar y actualizar libpve-storage-perl/libpvestorage-perl a ≥ 8.3.8 / ≥ 9.1.2 para cerrar el vector XXE.
    • Ejecutar apt full-upgrade y reiniciar el host para que los paquetes se carguen.

Opcionalmente, implementar un WAF interno que inspeccione las peticiones a /api2/json/access/ticket y rechace cualquier cuerpo que contenga el campo tfa-challenge sin un token de 2FA válido.

Cuándo aplicar esta solución

Aplica siempre que:

  • El panel de Proxmox sea accesible fuera del rango de red interno.
  • Se observen señales de compromiso como VMs apagadas, archivos .onyx o README_DESTROY.txt.
  • La versión de libpve-access-control está entre 7.0‑7 y < 8.0.4.

No es necesario si:

  • La interfaz está completamente aislada detrás de una VPN y no se usan credenciales sin 2FA.
  • El host ejecuta una versión de Proxmox VE 8.0.4 o superior con todos los parches aplicados.

Código

# 1. Verificar versiones vulnerables
V=$(dpkg-query -W -f='${Version}' libpve-access-control 2>/dev/null)
echo "libpve-access-control: ${V:-no instalado}"
dpkg --compare-versions "$V" ge 7.0-7 && \
dpkg --compare-versions "$V" lt 8.0.4 && \
echo ">>> VULNERABLE" || echo ">>> NOT vulnerable"

# 2. Bloquear acceso externo al puerto 8006 (ejemplo con nftables)
nft add table inet filter
nft add chain inet filter INPUT { type filter hook input priority 0 \; }
nft add rule inet filter INPUT ip daddr $PROXMOX_IP tcp dport 8006 ip saddr 10.0.0.0/24 accept
nft add rule inet filter INPUT ip daddr $PROXMOX_IP tcp dport 8006 drop

# 3. Habilitar 2FA para root@pam (comando interno de Proxmox)
pveum user modify root@pam -twofactor google-authenticator

Verificación

  1. Comprobar que el puerto está filtrado
    Desde una máquina externa: curl -kI https://IP_PROXMOX:8006/ debe devolver Connection timed out o refused.
    Desde la red interna: la misma petición debe responder 200 OK.

  2. Confirmar que el ticket de acceso requiere 2FA
    Ejecutar una petición POST sin tfa-challenge y observar que la respuesta contiene error: authentication required.

  3. Validar versiones
    El bloque anterior debe imprimir >>> NOT vulnerable. Si muestra >>> VULNERABLE, aplicar apt update && apt full-upgrade y reiniciar.

  4. Buscar indicadores de compromiso

    find / -xdev -name 'README_DESTROY.txt' -o -name '*DESTROY*' 2>/dev/null
    find /var/lib/vz -type f \( -name '*.onyx' -o -name 'README_DESTROY.txt' \) 2>/dev/null
    

    Ausencia de resultados indica que no hay rastros visibles de la campaña conocida.

Notas adicionales

  • Backups fuera del host: almacene copias en un servidor distinto o en un bucket S3 con políticas de retención que impidan la eliminación desde el nodo Proxmox.
  • Rotación de claves SSH: después de aplicar los parches, regenere todas las claves y revíselas en los archivos de configuración de VMs.
  • Monitoreo de API: habilite el registro de auditoría (/var/log/pveproxy/access.log) y configure alertas cuando se solicite /api2/json/access/ticket sin un token de 2FA.
  • Pruebas de penetración internas: utilice herramientas como curl o httpie para intentar el bypass antes de cerrar el puerto; esto confirma que el parche está activo.

Mantener la superficie de gestión cerrada y la autenticación reforzada evita que el escenario de apagado masivo y cifrado de datos se repita. La combinación de firewall, 2FA y actualización de paquetes constituye una defensa suficiente para la mayoría de los entornos de Proxmox en producción.