Quien administra servidores de hosting con panel de seguridad instalado recibió el 2 de noviembre una actualización firmada por su proveedor y, con ella, un backdoor. No fue un fallo del software ni una vulnerabilidad que alguien pudiera parchear a tiempo: alguien entró en el canal de distribución de cPGuard, el producto de la empresa OpsShield, y publicó código malicioso como si fuera una versión legítima.
El incidente lo destapó el propio proveedor el 3 de noviembre, un día después de que las actualizaciones envenenadas empezaran a salir, a las 02:06 UTC del 2 de noviembre. Las versiones afectadas son la 5.88.12 y las seis siguientes hasta la 5.88.19, según el repaso de incidentes que publicó el boletín Patchwork de heise el 4 de noviembre. La 5.88.25 elimina el backdoor y el script que lo instala.
La gravedad no está en lo que hizo el código, que es lo habitual en estos casos, sino en dónde se ejecutó. Un panel de control de hosting corre con privilegios de root, ve todas las cuentas del servidor y guarda las credenciales de las bases de datos que administra. Cualquier cosa que ese panel instale por su cuenta hereda el mismo nivel de confianza, y en este caso la heredó durante casi dos días en miles de máquinas.
¿Qué hacía el script y por qué no lleva CVE?
El script malicioso instalaba un backdoor y robaba datos del servidor. Los datos que un panel de hosting tiene a mano son los que hacen falta para volver a entrar sin pedir permiso: contraseñas de cuentas, credenciales de bases de datos, secretos de servicios cloud y claves SSH de los usuarios alojados.
No hay CVE asignado y no es un descuido administrativo. Un CVE describe una debilidad en el código que puede corregirse con un parche; aquí el código era correcto y el mecanismo de entrega, no. Lo que falló fue la cadena que convierte un commit en una actualización que miles de servidores aceptan sin preguntar de dónde viene, algo que ninguna base de datos de vulnerabilidades sabe describir.
Un fallo de código se puede auditar antes de instalar; una actualización que llega por el canal oficial, no. Esa asimetría es la que convierte al proveedor en parte de tu superficie de ataque.
Esa distinción importa para quien tiene que decidir qué hacer ahora. Un CVE se resuelve actualizando y comprobando la versión; un canal de distribución comprometido obliga a asumir que el atacante estuvo dentro del servidor con los máximos permisos y a tratarlo como una intrusión completa, no como un fallo pendiente de parche.
El CDN era el punto débil, no el código
La causa que documenta el proveedor es el robo de las credenciales de acceso al CDN que sirve las actualizaciones. Con esas credenciales en la mano, el atacante no necesita encontrar un fallo en el panel ni convencer a nadie: publica el paquete donde el panel lo va a buscar y espera a que los servidores se actualicen solos, que es exactamente lo que se les pide hacer.
Este patrón ya apareció dos veces en el sitio en las últimas semanas. La versión 1.107.0 de LiteLLM se distribuyó envenenada y robaba claves al arrancar Python, con el mismo mecanismo de fondo: el paquete que instalas no es el que el proyecto escribió. La diferencia es el nivel de privilegio. Una librería de Python comprometida ejecuta código con los permisos de la aplicación que la importa; un panel de hosting comprometido ejecuta código con los permisos de la máquina entera.
Hay un detalle incómodo que explica por qué estos ataques funcionan tan bien. Buena parte de la infraestructura que mueve internet depende de proyectos con equipos de una sola persona, y esos equipos no pueden permitirse un sistema de firma de paquetes con claves separadas del servidor de despliegue. Cuando la credencial del CDN vale tanto como la clave de firma, el candado no cierra nada.
El aviso del proveedor es explícito sobre lo que hay que rotar: contraseñas, credenciales de bases de datos, secretos cloud y claves SSH. La lista no es un trámite, es la descripción del botín. Un atacante con acceso al panel durante dos días pudo leer todo lo que el panel guarda en claro para poder conectarse a los servicios de sus clientes.
Ninguna de esas credenciales aparece en un escaneo de vulnerabilidades, porque no son un fallo: son el inventario que el panel necesita para funcionar y que un atacante puede leer completo en una sola consulta.
El orden de rotación debería seguir el daño, no la comodidad. Primero las claves SSH de los usuarios con acceso al servidor y las credenciales de la base de datos principal, porque con ellas se entra sin depender de nada más. Después los secretos de servicios cloud, que suelen dar acceso a almacenamiento y a facturación. Al final las contraseñas de las cuentas alojadas, que son muchas y cuya rotación forzada cuesta más explicar al cliente.
Rotar no basta si no se revisa qué se hizo con las credenciales mientras fueron válidas. Los registros de acceso del panel, las tareas programadas creadas en esas fechas y los usuarios añadidos al sistema son los tres sitios donde suele aparecer la huella de una intrusión que ya terminó. Quien solo cambie contraseñas y no mire esos tres registros se queda con la duda de si el atacante sigue dentro.
¿Cómo saber si tu servidor quedó expuesto?
La comprobación empieza por la versión instalada del panel. Si está entre la 5.88.12 y la 5.88.19, el servidor ejecutó código ajeno y hay que asumirlo como comprometido hasta que se demuestre lo contrario. Si está en la 5.88.25 o superior, el backdoor está eliminado, pero la rotación de credenciales sigue siendo necesaria porque eliminar el programa no invalida lo que ya se copió.
Conviene además revisar el histórico de actualizaciones del panel y cruzarlo con las fechas del incidente. Un servidor que no se actualizó en esos dos días pudo salvarse por pura dejadez, y merece la pena saberlo antes de ordenar una rotación masiva a todos los clientes.
La pregunta útil no es si el panel está actualizado hoy, sino cuándo se actualizó por última vez y quién podía publicar en su origen durante esos dos días de noviembre. La primera se responde con un vistazo; la segunda, casi nunca.
El aviso pide también revisar si el panel tiene activada la actualización automática, que en este caso fue el vector. Desactivarla ahora no habría evitado nada si el administrador hubiera actualizado a mano al día siguiente, así que la decisión sensata no es apagar las actualizaciones automáticas sino exigir que el proveedor las firme de una forma que él mismo no pueda falsificar.
El patrón que se repite en la cadena de suministro
En los últimos quince días el sitio ha cubierto tres incidentes con el mismo esqueleto: LiteLLM, el fallo de php2shell y ahora cPGuard. Ninguno de los tres nació de un error de programación brillante; los tres nacieron de una credencial de distribución mal protegida y de una comunidad que instala lo que el repositorio le sirve.
La lección práctica es que el inventario de software de un servidor ya no puede ser una lista de paquetes. Tiene que incluir de dónde vienen esos paquetes, quién puede publicar en ese origen y qué haría falta para falsificar una actualización. Esa información no aparece en ninguna herramienta de gestión de vulnerabilidades y es la que distingue a quien puede responder en dos horas de quien se enteró por la prensa.
Para los clientes de un hosting compartido la pregunta es más incómoda, porque no eligen el panel: solo pueden exigir que el proveedor publique su política de firma de actualizaciones y su plan de rotación.
Lo que un panel de hosting debería demostrar a partir de ahora
La versión 5.88.25 arregla este incidente concreto, pero no arregla el modelo. Un panel que se actualiza a sí mismo con credenciales que valen tanto como la clave de firma vuelve a ser vulnerable la próxima vez que alguien robe esas credenciales, y el próximo aviso tardará otra vez un día en llegar.
Lo razonable es pedir tres cosas a cualquier panel que corra como root: firma de paquetes con clave separada del servidor de despliegue, registro público de qué versión se publicó y cuándo, y capacidad de fijar una versión concreta sin que la automática la sobrescriba. Las tres existen en el ecosistema desde hace años y ninguna es cara de implementar. Mientras llegan, la respuesta es la misma de cada incidente de este tipo. Si tu panel estuvo entre las versiones afectadas, la versión nueva elimina el backdoor pero no deshace el robo. Las credenciales que pasaron por ese servidor durante dos días hay que darlas por comprometidas y cambiarlas todas, empezando por las que abren la puerta sin pedir nada más.