Ilustración abstracta de pintura fluida en tonos azul marino, rojo y blanco para la noticia: Una actualización falsa de cPGuard copió claves root en 2.950 servidores

Ciberataques

Una actualización falsa de cPGuard copió claves root en 2.950 servidores

cPGuard instaló como root un script que copió hashes, claves SSH y contraseñas de MySQL en unos 2.950 servidores de hosting. OpsShield pide rotarlo todo.

Unos 2.950 servidores Linux de hosting ejecutaron como root, entre las 02:08 y las 03:20 UTC del 2 de noviembre de 2026, una actualización de cPGuard que no había preparado OpsShield. El script copió los hashes de contraseñas del fichero shadow, las claves SSH de root, la contraseña de root de MySQL y el historial de la shell, y dejó un backdoor con setuid en /var/tmp, según el informe del incidente que el fabricante publicó el 3 de noviembre.

Diez horas desde una cuenta de prueba hasta la clave que publica las actualizaciones

cPGuard es la suite de seguridad de OpsShield para servidores de hosting con cPanel, DirectAdmin, Plesk y otros paneles. Incluye escáner de malware, WAF y protección frente a fuerza bruta, y su agente se actualiza solo consultando la infraestructura de distribución de la empresa, que SecurityWeek sitúa en la India. Ese canal de actualización es el que acabó en manos del atacante.

El informe de OpsShield reconstruye la intrusión con horas UTC. A las 15:38 del 1 de noviembre empezaron los sondeos contra manage.opsshield.com, el portal de facturación y licencias. A las 16:34 el atacante registró una cuenta de cliente con identidad falsa y pidió una prueba gratuita de cPGuard, y a las 21:17 instaló esa prueba en un servidor propio para estudiar cómo habla el agente con el sistema de licencias. El propio cPGuard lo marcó y lo bloqueó dos veces entre las 21:40 y las 21:51. A las 22:50 envió peticiones manipuladas a las páginas de callback del portal y ocho minutos después ya podía ejecutar comandos en el servidor de facturación y licencias, desde donde empezó a copiar datos.

Cronología publicada por OpsShield del ataque a cPGuard, desde el sondeo del portal de facturación hasta la actualización falsa del 2 de noviembre
Fuente: OpsShield, «Security Incident Disclosure: manage.opsshield.com»

Con esa posición obtuvo la clave de acceso al almacenamiento de actualizaciones. Entre las 02:04 y las 02:09 del 2 de noviembre subió las versiones falsas, 5.88.12 a 5.88.19, y a las 02:13 clonó tres servidores en la nube de la compañía. La empresa lo resume como «from first probe to fake update in about ten hours» (del primer sondeo a la actualización falsa en unas diez horas). Lo que OpsShield todavía no sabe es qué petición exacta le dio acceso al portal. Su informe admite que «Our logs do not record the exact request that gave them access» (nuestros registros no recogen la petición exacta que les dio acceso), descarta SSH, el panel de control, FTP y los tokens de API, y dice haber parcheado dos posibles puntos de entrada mientras revisa línea a línea los componentes de terceros de la aplicación de facturación. Es la misma incógnita con la que arrancó el backdoor de Rank Math PRO en octubre, otro proveedor pequeño cuya web de descargas sirvió código ajeno sin que nadie explicara al principio cómo.

Qué copió el script cpguard-v58812-i91511.sh y qué dejó en /var/tmp

OpsShield describe la actualización falsa con una frase, «The fake update was a short script, not a long-term implant» (la actualización falsa era un script corto, no un implante de larga duración). En cada servidor que lo ejecutó leyó los ficheros shadow y passwd del directorio /etc, el directorio /root/.ssh completo (claves privadas, authorized_keys y known_hosts), /root/.my.cnf con la contraseña de root de MySQL donde existía, el historial de la shell de root, que suele contener contraseñas y tokens tecleados, y, en un número pequeño de servidores, las claves de almacenamiento en la nube de /root/.s3cfg. Lo empaquetó en /var/tmp/.cpg91511/loot.tgz y lo subió al propio servidor de licencias de OpsShield, bajo una cuenta comprometida, para que el atacante lo recogiera después.

Dejó dos cosas atrás. La primera, una shell de root con setuid en /var/tmp/.cpg91511_sh. La segunda, una tarea programada en /etc/cron.d/i93677 con ficheros en /var/tmp/.i93677/. La actualización limpia elimina la shell y una segunda actualización retira la tarea de cron, pero nada de eso invalida lo que ya salió del servidor.

El aviso técnico de OpsShield indica cómo saber si un servidor instaló alguna de las versiones envenenadas: basta con buscar en el registro de instalación del agente.

grep 'Successfully updated' /opt/cpguard/logs/install_log

La captura del aviso muestra las entradas de ejemplo que publica el fabricante, con instalaciones de 5.88.12 a 5.88.19 repartidas entre las 02:46 y las 12:46 del 2 de noviembre.

Aviso de OpsShield con el comando para revisar el historial de actualizaciones de cPGuard y las entradas de ejemplo de las versiones 5.88.12 a 5.88.19
Fuente: OpsShield, «cPGuard security advisory: Update channel compromise»

Ese ejemplo abre una duda que el fabricante no ha aclarado. El informe del 3 de noviembre acota la instalación de la actualización falsa a 72 minutos, de 02:08 a 03:20 UTC, mientras que el aviso técnico sitúa la última versión afectada, la 5.88.19, a las 12:46 y afirma que la empresa detectó el ataque en las 12 horas siguientes al lanzamiento de esas versiones. Las dos cosas pueden ser ciertas si el script solo se ejecutó en la primera instalación y las siguientes versiones falsas no hacían nada nuevo, pero OpsShield no lo dice. Quien revise su registro no debería dar por limpio un servidor porque su entrada sea posterior a las 03:20.

OpsShield también avisa de que una entrada en ese registro confirma la instalación de una versión afectada, pero no qué ficheros se recogieron ni si salieron del servidor, y de que un registro sin entradas o incompleto tampoco prueba que el servidor esté limpio. Desde la versión 5.88.25 el agente retira el backdoor conocido y los ficheros preparados por el script, y el informe del 3 de noviembre habla de la 5.88.26 como la actualización limpia publicada el día 2. La comprobación de la versión instalada se hace con el cliente de línea de comandos del producto.

cpgcli update --start
cpgcli --version

2.950 servidores, 7.900 cuentas y 32 ficheros, el alcance que OpsShield puede medir y el que no

El informe cifra en unos 2.950 los servidores de clientes que ejecutaron la actualización falsa y en unos 7.900 las cuentas del portal de facturación cuyos registros (nombre, empresa, dirección postal, correo y contraseña con hash bcrypt) copió el atacante desde el servidor de licencias. A BleepingComputer, un portavoz de la empresa le dio una cifra más precisa: «We detected 2946 servers were affected» (detectamos que 2.946 servidores se vieron afectados), según recoge el artículo del medio del 3 de noviembre. La tabla del propio informe resume quién está expuesto y a qué.

Tabla de OpsShield con el alcance del incidente de cPGuard, unos 2.950 servidores y 7.900 cuentas del portal de facturación
Fuente: OpsShield, «Security Incident Disclosure: manage.opsshield.com»

Hay una tercera cifra que conviene leer con cuidado. La actualización del aviso técnico fechada a las 02:42 IST del 3 de noviembre estima que el atacante recuperó 32 de los ficheros subidos al servidor de licencias, cada uno correspondiente a un servidor de cliente distinto. OpsShield lo presenta como una estimación preliminar de la recuperación confirmada, no como el total de servidores afectados, y su recomendación general no distingue: si el servidor tenía cPGuard instalado y en línea en la ventana del 2 de noviembre, «assume its root-level secrets are known to the attacker» (da por hecho que el atacante conoce sus secretos de root). El agente no comprueba actualizaciones de forma continua, así que los servidores que estaban apagados o sin conexión en ese intervalo no recibieron la versión falsa, aunque sus administradores deben cambiar igualmente la contraseña del portal de facturación.

Sobre lo que pasó dentro de los servidores de clientes después de la recogida, el fabricante dice no haber identificado más actividad maliciosa que la descrita, con la salvedad de que la investigación sigue abierta. Para un grupo reducido de clientes la situación es distinta: OpsShield ha avisado de forma individual a aquellos en cuyos servidores el atacante llegó a iniciar sesión a mano, y a esos les recomienda reconstruir el servidor desde una copia anterior al 1 de noviembre. Para el resto no recomienda por ahora reinstalar el sistema operativo, una decisión que la propia empresa califica de provisional.

El ángulo español es, de momento, una ausencia. En el momento de escribir esta noticia, la tarde del 4 de noviembre de 2026, ni INCIBE-CERT ni CCN-CERT habían publicado aviso sobre el incidente y ningún proveedor de hosting español había confirmado públicamente que use cPGuard, aunque el producto se vende para los mismos paneles cPanel, DirectAdmin y Plesk que dominan el hosting compartido en España. La cuenta de inteligencia Dark Web Intelligence fue de las primeras en difundir el aviso en X, la tarde del 3 de noviembre, con el resumen de las versiones afectadas.

Hashes, rutas y una dirección IP para buscar en servidores con cPanel y DirectAdmin

OpsShield publica los indicadores de compromiso tanto del lado de los clientes como de sus propios servidores internos, y advierte de que los tres últimos (el backdoor gsocket, el implante en Go y el script que lo oculta) solo se han visto en su infraestructura, no en servidores de clientes. Los nombres de fichero del atacante siguen el patrón i9xxxx. Como el implante interno se esconde de ps, netstat, ls y find, la empresa recomienda buscarlo desde un entorno de arranque de confianza o con binarios estáticos conocidos.

Tipo

Valor

Contexto

IP

94.183.188.91

Dirección principal del operador, usada contra el portal de facturación de OpsShield

user-agent

cPGuard/5.88.11

Cabecera falsa con la que la IP del atacante imitaba al agente legítimo

ruta de archivo

/i90248_probe.txt

Fichero de sondeo dejado en la raíz web del portal de facturación

ruta de archivo

/i90573_probe.txt

Fichero de sondeo dejado en la raíz web del portal de facturación

ruta de archivo

/i90573_sh.php

Webshell en la raíz web del portal de facturación

ruta de archivo

/i90573_x.php

Webshell en la raíz web del portal de facturación

URL

*_rx.php

Rutas que el atacante usó para recibir los datos robados

ruta de archivo

cpguard-v58812-i91511*.sh

Scripts de la actualización falsa, cuatro variantes

hash SHA-256

2c2acd988da531d133d0e17f245c49bf15781278f837543d18c95e8410eabd38

cpguard-v58812-i91511.sh

hash SHA-256

ffd7a47f65fa1244429baa936ae94be54676b53d2f88bc39564f24e22011de8a

cpguard-v58812-i91511b.sh

hash SHA-256

d73919af84bf46de941db85e27fd1abc65701ef9ce6cf33bb27c5397f4a41c26

cpguard-v58812-i91511c.sh

hash SHA-256

6add0201e9a3d02de772d561d05e0da86eb1c538686753b7adcc3aedf7366f77

cpguard-v58812-i91511d.sh

ruta de archivo

/var/tmp/.cpg91511_sh

Shell de root con setuid dejada por la actualización falsa

ruta de archivo

/var/tmp/.cpg91511/loot.tgz

Archivo con los ficheros recogidos antes de subirlos al servidor de licencias

ruta de archivo

/etc/cron.d/i93677

Tarea programada dejada por la actualización falsa

ruta de archivo

/var/tmp/.i93677/

Directorio de la tarea programada dejada por la actualización falsa

ruta de archivo

/usr/bin/defunct

Backdoor gsocket en los servidores internos de OpsShield, proceso visible como [slub_flushwq]

ruta de archivo

/lib/systemd/system/defunct.dat

Unidad defunct.service del backdoor gsocket, solo en servidores internos de OpsShield

ruta de archivo

/usr/sbin/pythno3

Copia del implante en Go en servidores internos de OpsShield, proceso visible como [rcu_gp]

ruta de archivo

/usr/sbin/netstat.cfg

Copia del implante en Go, solo en servidores internos de OpsShield

ruta de archivo

/etc/profile.d/bash.cfg

Copia del implante en Go, solo en servidores internos de OpsShield

ruta de archivo

/usr/lib/system.mark

Copia del implante en Go, solo en servidores internos de OpsShield

ruta de archivo

/usr/lib/libgdi.so.0.8.2

Copia del implante en Go, solo en servidores internos de OpsShield

ruta de archivo

/boot/system.pub

Copia del implante en Go, solo en servidores internos de OpsShield

ruta de archivo

/etc/profile.d/gateway.sh

Oculta el implante a ps, netstat, ls y find en servidores internos de OpsShield

La IP 94.183.188.91 enviaba en ocasiones un user-agent falso cPGuard/5.88.11, imitando al agente legítimo, y los ficheros *_rx.php eran los puntos de recepción de los datos robados en el portal de facturación. Son indicadores que sirven para revisar los registros de acceso de cualquier aplicación web expuesta, también en empresas que nunca han instalado cPGuard.

Rotar las claves de root, SSH y MySQL después de actualizar a 5.88.26

Las medidas de OpsShield, ordenadas por urgencia, caben en una hora por servidor según la propia empresa. La lista añade a quién avisar en España y qué buscar en los registros.

  1. Actualiza cPGuard con cpgcli update --start en todos los servidores y confirma con cpgcli --version que la versión instalada es la 5.88.25 o posterior (5.88.26 según el informe). Comprueba después que /etc/cron.d/i93677, /var/tmp/.i93677/ y /var/tmp/.cpg91511_sh han desaparecido y bórralos si siguen ahí.
  2. Busca en /opt/cpguard/logs/install_log cualquier entrada de 5.88.12 a 5.88.19. Si aparece, trata el servidor como comprometido aunque ya ejecute una versión limpia.
  3. Cambia la contraseña de root y la de todas las cuentas locales con contraseña desde un entorno de recuperación de confianza, y desde otro equipo cambia las que estuvieran reutilizadas en otros sistemas.
  4. Genera nuevas claves SSH para root, retira las antiguas del authorized_keys de todos los servidores que confiaban en ellas y revisa ese fichero en busca de claves que no reconozcas. Los servidores a los que se llegaba por SSH desde el afectado quedan expuestos hasta que sus claves se reemplacen.
  5. Cambia la contraseña de root de MySQL o MariaDB y cualquier otra credencial de base de datos guardada en /root/.my.cnf.
  6. Rota toda contraseña, clave de API o token que aparezca en el historial de la shell de root, las claves S3 de /root/.s3cfg y los tokens de DigitalOcean.
  7. Restablece la contraseña del portal manage.opsshield.com y activa el segundo factor. OpsShield ya ha cerrado todas las sesiones del portal y está reemitiendo todos los pares de claves de licencia de cPGuard, así que las copias en manos del atacante dejarán de servir.
  8. Si OpsShield te ha comunicado que el atacante inició sesión a mano en tu servidor, reconstrúyelo desde una copia limpia anterior al 1 de noviembre.
  9. Si confirmas el acceso o la salida de credenciales, notifícalo a INCIBE-CERT si eres empresa o particular y al CCN-CERT si perteneces al sector público, y valora si los datos de clientes alojados obligan a comunicar una brecha a la AEPD en el plazo de 72 horas.

Para buscar las huellas del script y del backdoor sin confiar en las herramientas del propio sistema, estas comprobaciones recorren las rutas que publica OpsShield y la tarea de cron.

ls -la /var/tmp/.cpg91511_sh /var/tmp/.cpg91511 /var/tmp/.i93677 /etc/cron.d/i93677 2>/dev/null
find / -xdev -type f -perm -4000 -newermt '2026-11-01' 2>/dev/null
grep -rl 'i91511\|i93677' /etc/cron.d /var/spool/cron 2>/dev/null
last -F root | head -n 30

El segundo comando busca binarios con setuid creados desde el 1 de noviembre, que es la forma de encontrar la shell aunque la hayan renombrado. La salida de last conviene contrastarla con el journal de sshd, porque un atacante que ya tiene la clave privada de root no necesita ningún exploit para volver.

Junto a la limpieza en los servidores de clientes, OpsShield ha revocado la clave robada del almacenamiento de actualizaciones y todos los tokens de API de su cuenta en la nube, ha eliminado la clave SSH del atacante y los servidores clonados, ha reemplazado todas las claves y contraseñas de sus propios servidores, ha rotado las claves de API de facturación y de revendedores y está reconstruyendo desde cero los servidores de facturación, licencias y gestión interna. También prepara una actualización que elimina las claves de acceso de su soporte técnico de los servidores donde los clientes las habían añadido, un detalle que conviene retener: durante años el fabricante tuvo acceso remoto a muchos de esos servidores y no ha dicho si la clave privada correspondiente estaba al alcance del atacante.

Un agente con root que se actualiza solo y un proveedor pequeño en el punto de mira

La cadena de este ataque no tiene un exploit memorable. Tiene una aplicación de facturación con un fallo que nadie ha identificado aún, una clave de publicación guardada en un servidor que no debería tenerla y un agente de seguridad que ejecuta como root cualquier cosa que le llegue por su canal de actualización. Con esas piezas, el atacante convirtió en diez horas una cuenta de prueba gratuita en acceso de root a casi tres mil servidores de hosting, y cada uno de ellos aloja a su vez decenas o cientos de webs de terceros. El perímetro real del incidente lo marcan los clientes de esas 2.950 máquinas, y de eso el informe no dice nada porque OpsShield no puede saberlo.

Desde mediados de octubre este blog ha contado más de media docena de casos en los que el canal oficial de un proveedor entregó el código del atacante, desde los binarios de OVHcloud CLI en GitHub y el stealer de LiteLLM 1.107.0 en PyPI hasta la extensión de Claude Code en el marketplace de Cursor y el script de DebugBear que vació carteras en Polymarket. La tabla pone en fila los cinco más comparables con el de cPGuard, con las cifras que publicaron sus proveedores.

Proveedor y canal

Fecha

Ventana de exposición

Qué entregó

Rank Math PRO, descargas desde la web del plugin

15 y 16 de octubre de 2026

Unas 11 horas, de 20:02 a 07:12 UTC

Backdoor PHP en webs WordPress

OVHcloud CLI, releases de GitHub

19 de octubre de 2026

94 minutos, unas 250 descargas

Stealer de credenciales de nube, Kubernetes y SSH

LiteLLM 1.107.0, PyPI y Docker Hub

21 de octubre de 2026

104 minutos en PyPI

Stealer y backdoor que arranca con cualquier proceso Python

Claude Code 2.1.313, marketplace de Cursor

29 de octubre de 2026

11 horas, hasta 5.000 usuarios

Clave SSH del atacante y túnel inverso

DebugBear, script cargado por Polymarket

29 de octubre de 2026

52 minutos

Drainer que vació 726 carteras

cPGuard 5.88.12 a 5.88.19, canal de actualización

2 de noviembre de 2026

72 minutos, unos 2.950 servidores

Script que copia secretos de root y deja una shell setuid

La diferencia de cPGuard con los demás está en el privilegio. Una extensión de editor corre con los permisos del usuario y un script web con los de la pestaña, pero un agente de seguridad de servidor corre como root y por diseño toca el fichero shadow y el directorio /root/.ssh. Quien confía la seguridad de su hosting a un agente así debería preguntar a su proveedor si las actualizaciones van firmadas y el agente verifica la firma, dónde vive la clave que las firma y cada cuánto consulta el agente el canal, porque OpsShield no publicaba nada de eso antes del incidente. Las herramientas DevSecOps que el blog recopila sirven para inventariar ese tipo de dependencias, pero el inventario no sustituye a la pregunta.

OpsShield ha hecho dos cosas bien. Publicó un informe con horas, cifras e indicadores un día después de detectar el ataque y reconoció por escrito lo que no sabe. También atribuye la velocidad del ataque al uso de herramientas de IA por parte del atacante, una afirmación que no acompaña de ninguna prueba y que nosotros no podemos contrastar, así que la dejamos como opinión del fabricante. Hay un dato que sí se puede medir. Un proveedor con unos 7.900 clientes y acceso de root a sus servidores era un objetivo tan rentable como cualquier gran fabricante, y bastante menos vigilado. Ese cálculo lo hizo alguien el 1 de noviembre a las 15:38 UTC, y seguirá siendo válido para el siguiente proveedor pequeño con un agente privilegiado y un portal de facturación en PHP.

Temas

No hay comentarios todavía