SSD Nodes Learn 🎉 VPS desde $5.50/mes
Guías Matt ConnorPor Matt Connor

Como recuperar un VPS tras un compromiso de seguridad

Si su VPS ha sido vulnerado, no intente limpiar el sistema. Aísle el servidor, cree un snapshot para análisis forense, rote todas las claves y reinstale desde una imagen limpia.

No limpie un VPS comprometido

Si su VPS ha sido vulnerado, la decisión más importante se toma antes de ejecutar cualquier comando. No intente limpiar la máquina. Aíslela desde el panel del proveedor, cree una instantánea del disco como evidencia, rote todas las credenciales que contenía y, a continuación, realice una reinstalación en un servidor nuevo utilizando fuentes de confianza.

No puede demostrar que un rootkit ha sido eliminado, porque las herramientas necesarias para probarlo son las mismas que controla el atacante.

Ese es el argumento completo. Este es el mecanismo detrás de ello. Un atacante que ha obtenido acceso root puede reemplazar ps para que un ID de proceso nunca aparezca en su salida. Una línea en /etc/ld.so.preload carga código del atacante en cada programa vinculado dinámicamente en el sistema, por lo que ls, ss y find mienten de la misma manera consistente. Un módulo de kernel cargable puede ocultar archivos por debajo de la llamada al sistema, de modo que incluso un binario recién descargado vea un disco limpio. Usted elimina el minero, el gráfico de CPU desciende y el servidor se queda en silencio. El silencio es también el estado en el que se encuentra una puerta trasera funcional.

Reinstalar cuesta menos de lo que parece. Un VPS típico consiste en un puñado de paquetes, un directorio de configuración y un conjunto de datos, por lo que una reinstalación es una tarea finita con un final claro. Buscar cada cambio realizado por un atacante es una tarea sin fin y nunca llega a ofrecer garantías.

Confirmar si realmente se trata de una brecha

Muchos servidores reportados como hackeados no lo están. Miles de intentos fallidos de inicio de sesión por SSH al día son ruido de fondo de Internet, ya que cada dirección IPv4 pública se escanea continuamente. Una salida de lastb llena de intentos de root y admin significa que los escáneres encontraron su puerto. No significa que alguien haya entrado.

Estas señales sí son relevantes:

  • Un inicio de sesión exitoso que usted no puede justificar, como Accepted password for root from 203.0.113.7.
  • Una clave en authorized_keys que usted no añadió.
  • Un aviso de abuso de su proveedor sobre tráfico saliente desde su servidor.
  • Un proceso al 100% de CPU con un nombre copiado de un hilo del kernel. Los mineros instalados a través de sockets de Redis y Docker expuestos suelen reportarse bajo nombres como kdevtmpfsi y kinsing.
  • Conexiones salientes a direcciones que ninguno de sus servicios utiliza.

El disfraz de hilo del kernel tiene una prueba rápida. Los hilos reales del kernel se imprimen entre corchetes y no tienen un ejecutable detrás, por lo que sudo ls -l /proc/<pid>/exe falla para ellos con No such file or directory. Si un proceso impreso como [kworker/0:2] tiene un enlace exe que apunta a algo bajo /tmp, es un programa de usuario común usando un nombre de kernel.

Ejecute estas comprobaciones sabiendo que el sistema podría estar engañándole. Son suficientes para determinar que algo va mal. No son suficientes para determinar que todo está bien.

Corte la red desde el proveedor, no desde el interior del servidor

El aislamiento es lo primero, ya que cualquier paso posterior es inútil mientras alguien más mantenga una shell. Leer registros, rotar claves y restaurar datos no tiene sentido si un atacante activo está observando.

Realice esta acción en el panel de control de su proveedor, en el firewall de red que se ejecuta fuera de su sistema operativo. Deniegue el tráfico entrante y saliente, y utilice la consola web como su única vía de acceso. Las reglas aplicadas allí prevalecen sobre cualquier evento que ocurra en el disco.

Existen dos razones para no hacer esto desde el interior del servidor. Un firewall configurado dentro de un kernel comprometido es aplicado por ese mismo kernel, y root puede vaciar nftables con la misma facilidad con la que usted lo escribe. Además, sudo ip link set enp1s0 down a través de SSH corta su propia sesión primero, lo que le bloquea el acceso a una máquina que estaba examinando.

Bloquee tanto el tráfico saliente como el entrante. Una reverse shell se conecta desde su servidor hacia el atacante, por lo que un bloqueo solo de entrada deja una conexión establecida funcionando perfectamente. Si su proveedor solo ofrece reglas de entrada, las opciones restantes son desconectar la interfaz de red o apagar la instancia.

No reinicie todavía. Compruebe primero si existe /var/log/journal. Si ese directorio no está presente, journald está escribiendo en /run/log/journal, que reside en la memoria, por lo que un reinicio borrará el registro de la intrusión. Los procesos en ejecución también desaparecen al reiniciar, y sus líneas de comandos suelen ser la evidencia más clara que podrá obtener.

Realice una instantánea del disco antes de tocar nada

Una instantánea y una copia de seguridad cumplen funciones distintas en este caso. La instantánea que realice ahora es una copia de un disco comprometido: es su prueba y es lo único que le permite volver atrás si sobrescribe algo por accidente. Sus copias de seguridad antiguas son la vía de recuperación. Si el panel de su proveedor utiliza ambos términos de forma imprecisa, lea primero cómo difieren las instantáneas de VPS de las copias de seguridad reales, ya que las reglas de retención y el comportamiento de restauración no son iguales.

Realice la instantánea desde el panel del proveedor antes de volver a iniciar sesión. Una instantánea en vivo es consistente ante bloqueos: captura el disco tal como estaba en ese instante, igual que si desconectara la alimentación. Eso es suficiente para obtener pruebas. Asígneles un nombre de modo que nadie las restaure por error. Algo tan directo como COMPROMISED-do-not-restore-2026-08-12 es el nivel de sutileza adecuado. Consérvela hasta que su investigación haya terminado y cualquier ticket de abuso con su proveedor esté cerrado.

Cómo acceder cuando SSH no está disponible

Existen dos vías, ambas desde el panel del proveedor. La consola web (VNC o serie) se conecta a la máquina como si hubiera conectado un teclado físico. Funciona cuando sshd está caído, cuando el firewall es incorrecto o cuando un atacante ha cambiado el puerto SSH. Se autentica con una contraseña local, por lo que un servidor configurado solo con claves podría requerir un restablecimiento de la contraseña de root antes de que la consola sea útil.

El modo de rescate es la mejor opción. Inicia un sistema live pequeño con su disco conectado pero sin ejecutarlo, por lo que sus comandos son fiables: el kernel comprometido y los binarios comprometidos no se están ejecutando. Monte el disco en modo de solo lectura.

lsblk -f
sudo mkdir -p /mnt/victim
sudo mount -o ro /dev/vda1 /mnt/victim

Si lsblk muestra volúmenes LVM (logical volume manager) en lugar de una partición simple, actívelos primero con sudo vgchange -ay y luego monte el dispositivo que aparece bajo /dev/mapper/.

No haga chroot en el disco montado para examinarlo. Un chroot ejecuta los binarios del atacante con sus permisos, lo cual invalida el motivo principal por el que inició el modo de rescate.

Recopile la evidencia que aún sea fiable

Ejecute estos comandos desde el modo de rescate, con el disco montado en modo de solo lectura en /mnt/victim. Comience por los inicios de sesión, ya que datan la intrusión y todo lo demás es más sencillo una vez que dispone de una ventana temporal.

sudo grep -aE 'Accepted (password|publickey)' /mnt/victim/var/log/auth.log
sudo last -f /mnt/victim/var/log/wtmp
sudo lastb -f /mnt/victim/var/log/btmp
sudo journalctl -D /mnt/victim/var/log/journal -u ssh --since "2026-07-01"

La ausencia de /var/log/auth.log no es sospechosa por sí misma. Algunas imágenes actuales de Ubuntu se distribuyen sin rsyslog, por lo que sshd registra los eventos únicamente en el journal, que es lo que lee la línea journalctl -D. Lo que merece atención es un vacío en registros que deberían ser continuos o un archivo de registro truncado a cero bytes. El borrado de registros es común y suele ser poco cuidadoso.

A continuación, las cuentas y las claves.

sudo find /mnt/victim/root /mnt/victim/home -name 'authorized_keys*' -exec ls -l {} +
sudo awk -F: '$3 == 0 {print $1}' /mnt/victim/etc/passwd
sudo lsattr /mnt/victim/root/.ssh/authorized_keys

La línea awk imprime todas las cuentas con ID de usuario 0. Cualquier resultado distinto a root indica una segunda cuenta root. El patrón find busca deliberadamente authorized_keys2 también, ya que OpenSSH lee ambos nombres de archivo por defecto y el segundo es fácil de pasar por alto. Si lsattr muestra una i en la lista de atributos, el archivo es inmutable: un atacante establece ese flag para que su intento de borrar la clave falle con Operation not permitted, y un administrador cansado podría asumir erróneamente que la edición tuvo éxito.

La persistencia se oculta en un número reducido de ubicaciones, así que revíselas todas.

sudo ls -lt /mnt/victim/etc/systemd/system
sudo ls -l /mnt/victim/etc/cron.d /mnt/victim/var/spool/cron/crontabs
sudo cat /mnt/victim/etc/ld.so.preload
sudo grep -rnE 'curl|wget|base64|/dev/tcp' /mnt/victim/etc/update-motd.d /mnt/victim/etc/rc.local /mnt/victim/root/.bashrc /mnt/victim/root/.profile

/etc/ld.so.preload no existe en un sistema Ubuntu o Debian estándar, por lo que No such file or directory es el resultado esperado; cualquier contenido merece su atención. Un archivo de inicio de sesión que redirija la salida de base64 -d a una shell es el mismo caso: una configuración legítima no necesita ocultar su propio texto.

Construya la línea temporal basándose en el tiempo de cambio (ctime) en lugar del tiempo de modificación (mtime).

sudo find /mnt/victim -xdev -newerct '2026-08-01' -type f -printf '%TF %TT %p\n' | sort

touch establece el tiempo de modificación en cualquier valor que el atacante desee, por lo que el mtime es engañoso. El tiempo de cambio (ctime) se actualiza ante cualquier modificación en el inodo y touch no puede retrocederlo, por lo que -newerct ofrece una lista más honesta de lo que se escribió recientemente. Aun así, no es una prueba definitiva, ya que root puede modificar el reloj del sistema o escribir directamente en el dispositivo de bloques.

La integridad de los paquetes merece un comando y una advertencia. En un sistema en ejecución, sudo dpkg --verify imprime una línea por cada archivo empaquetado cuya suma de comprobación ya no coincide, mostrando una 5 en la columna de suma, y sudo debsums -ac realiza la misma tarea incluyendo archivos de configuración cuando el paquete debsums está instalado. Interprete el resultado en una sola dirección. Un archivo /usr/sbin/sshd modificado es evidencia real. Un informe limpio no prueba nada, ya que la misma cuenta root que reemplazó el binario puede reescribir las listas de sumas de comprobación bajo /var/lib/dpkg/info/. Los escáneres de rootkits como rkhunter y chkrootkit siguen la misma regla: un hallazgo es información, una ejecución limpia no es una certificación de seguridad.

Copie lo que ha recopilado fuera de la máquina antes de realizar cualquier acción destructiva.

sudo tar --ignore-failed-read -C /mnt/victim -czf /root/evidence-2026-08-12.tgz \
  var/log etc root/.ssh root/.bash_history home
sha256sum /root/evidence-2026-08-12.tgz

Anote ese hash en un lugar fuera del servidor. Si esto se convierte en una reclamación de seguro o un informe policial, poder demostrar que el archivo no ha cambiado desde su recopilación marca la diferencia entre una evidencia y una simple carpeta de archivos. Borrar elementos por accidente durante una investigación es normal, y la instantánea junto con este archivo es lo que permite recuperarse. Deshacer un comando rm mal ejecutado es mucho más difícil de lo que la gente espera, tal como explica recuperar archivos borrados con rm -rf.

Identifique la puerta de entrada

Una reconstrucción que no cierra la ruta de entrada provoca una nueva brecha, a menudo en cuestión de días, ya que el escaneo que le detectó la primera vez nunca se detiene. Cuatro puertas cubren la mayoría de las brechas en servidores individuales.

Inicio de sesión por contraseña SSH. Una línea Accepted password for root desde una dirección que no reconoce es la respuesta por sí misma. Compruebe PasswordAuthentication en /etc/ssh/sshd_config y en cada archivo bajo /etc/ssh/sshd_config.d/. sshd utiliza el primer valor que obtiene para una palabra clave, y la línea Include se sitúa en la parte superior del archivo principal en Ubuntu, por lo que un archivo de configuración añadido prevalece silenciosamente sobre el ajuste que editó más abajo.

Un servicio publicado sin autenticación. Redis en 6379, la API de Docker en 2375, una base de datos vinculada a 0.0.0.0 en lugar de 127.0.0.1. Docker es la sorpresa común. Publicar un puerto de contenedor inserta reglas DNAT (traducción de direcciones de red de destino) que se evalúan antes que las cadenas de ufw, por lo que ufw status puede informar de un puerto como bloqueado mientras el contenedor detrás de él responde a todo internet. Entienda esto antes de la reconstrucción: por qué los puertos publicados por Docker omiten ufw cubre el orden de las reglas y la solución.

Una aplicación web sin parches. Busque en el registro de acceso del servidor web alrededor de su marca de tiempo sospechosa más antigua un POST a una ruta de carga o una ruta de administración, luego busque archivos bajo la raíz web con una hora de modificación coincidente. Un archivo PHP perdido en un directorio de subidas es el resultado clásico.

Una credencial filtrada. Una clave confirmada en un repositorio, un token pegado en un chat, un archivo .env servido como archivo estático por un servidor web mal configurado. La automatización facilita que esto ocurra por accidente, lo cual es el argumento para mantener los secretos fuera de los agentes de IA y sus archivos de configuración.

Si no puede identificar la puerta después de todo esto, asuma que hubo una credencial filtrada y trate cada secreto que la máquina contenía como público.

Rotación de todas las credenciales expuestas

Realice la rotación después de cortar el acceso a la red, nunca antes. Rotar las credenciales mientras el atacante mantiene la conexión solo le entrega los nuevos secretos.

  • Toda clave privada SSH almacenada en el servidor, además de cualquier cuenta externa que confiara en la clave pública correspondiente.
  • Cualquier clave que haya reenviado al equipo mediante ssh -A. El reenvío de agentes deja un socket en /tmp; el usuario root en esa máquina puede utilizarlo para autenticarse como usted en cualquier lugar donde su clave sea aceptada, mientras su sesión permanezca abierta.
  • Tokens de API en archivos .env, en líneas Environment= de systemd, en configuraciones de CI y en credenciales de proveedores.
  • Contraseñas de bases de datos y las cuentas de aplicación que las utilizan.
  • Claves privadas TLS (transport layer security) que el servidor poseía. Reemita el certificado y revoque el anterior.
  • La contraseña de su cuenta de alojamiento, con la autenticación de dos factores activada. Ese panel puede reconstruir, realizar instantáneas y acceder por consola a todos sus servidores, por lo que constituye el perímetro real.
  • Cualquier contraseña escrita en una sesión de shell en ese host mientras estuvo comprometido, ya que el usuario root puede registrar una sesión de terminal en tiempo real.

Si una contraseña utilizada en esa máquina se emplea en cualquier otro lugar, cámbiela también allí. La reutilización es la forma en que un VPS comprometido se convierte en una cuenta de correo electrónico comprometida.

Lista de verificación para la reconstrucción

  1. Cree un servidor nuevo a partir de una imagen de distribución limpia. No utilice una instantánea del servidor comprometido ni una restauración completa del sistema de archivos raíz.
  2. Instale los paquetes desde los repositorios de la distribución. Nunca copie binarios desde el disco antiguo.
  3. Restaure únicamente los datos desde una copia de seguridad anterior a la fecha más antigua detectada en su cronología. Esto incluye volcados de bases de datos, archivos subidos y el estado de la aplicación. Deje atrás /etc, /usr y los archivos de unidad antiguos.
  4. Introduzca las credenciales rotadas manualmente. No copie el archivo .env antiguo.
  5. Inspeccione el contenido web restaurado en busca de archivos añadidos durante el periodo de intrusión antes de volver a publicarlo.
  6. Refuerce la seguridad antes de exponer el servidor: utilice solo claves SSH, una cuenta de trabajo sin privilegios de root, un firewall con política de denegación predeterminada y no publique ningún servicio más allá de lo estrictamente necesario. Siga los pasos de los primeros diez minutos en un VPS nuevo, después refuerce SSH correctamente y añada fail2ban en Ubuntu 24.04 para reducir el ruido en los intentos de inicio de sesión. Asigne a cada servicio su propia cuenta con privilegios mínimos para que el próximo punto de acceso no sea una cuenta root.
  7. Apague el servidor antiguo y conserve su instantánea hasta que la investigación y cualquier ticket de abuso estén cerrados.
  8. Corrija las copias de seguridad. Si el paso 3 fue una suposición, la lección real es que su historial de copias de seguridad era demasiado corto para alcanzar un punto anterior a la intrusión. Las copias de seguridad externas, versionadas y con una retención prolongada son las que garantizan un punto de restauración limpio la próxima vez: copias de seguridad con restic en un VPS le proporciona ambas cosas.

Si no puede determinar la fecha de la intrusión, no podrá elegir una copia de seguridad segura. En ese caso, restaure solo los datos que pueda inspeccionar visualmente: un volcado SQL que pueda leer o un directorio de imágenes que pueda listar. Considere sospechoso cualquier archivo ejecutable y reinstálelo desde los repositorios.

Qué significa el aviso de abuso de su proveedor

La mayoría de los usuarios descubre que su servidor ha sido vulnerado a través de su proveedor, no por su propia monitorización. Los proveedores detectan el tráfico saliente: ataques de fuerza bruta SSH contra otras redes, spam en el puerto 25 o participación en un ataque de reflexión. El ticket suele incluir marcas de tiempo, puertos y una muestra de los flujos, junto con un plazo de resolución medido en horas.

Responda al aviso, aunque su única respuesta sea que el servidor está aislado y en proceso de reconstrucción. Los proveedores aplican un null-route o suspenden el servidor cuando un ticket queda sin respuesta, lo que convierte su incidente en una interrupción del servicio. Solicite las líneas de registro originales que respaldan el informe. Esas marcas de tiempo se registraron fuera de su máquina, por lo que son la única parte de la línea temporal que el atacante no pudo modificar; a menudo, datan la intrusión con mayor precisión que cualquier dato en el disco.

Un servidor de cliente vulnerado es una tarea rutinaria para un proveedor, y gestionar la situación correctamente no le perjudicará. La cuestión más amplia sobre si el hosting VPS es seguro depende principalmente de la configuración del cliente, que es exactamente la parte que ahora debe realizar de nuevo desde cero.

Cuándo contactar con un profesional

  • El servidor contenía datos personales de terceros. Según el RGPD (Reglamento General de Protección de Datos), cualquier brecha de seguridad que afecte a datos personales debe notificarse a la autoridad de control sin dilación indebida y, de ser posible, en un plazo máximo de 72 horas desde que se tenga constancia. Determinar si ese plazo ha comenzado es una tarea legal, no de administración de sistemas.
  • Había datos de tarjetas de pago involucrados. Los emisores de tarjetas exigen un investigador forense certificado; manipular el sistema por su cuenta puede invalidar las pruebas.
  • Existe una demanda de extorsión o sus datos han sido cifrados.
  • La máquina tenía acceso a otros equipos: una red interna, un hipervisor o un ejecutor de CI que contenga credenciales de producción. Un host comprometido en un grupo se considera un incidente que afecta a todo el grupo hasta que se demuestre lo contrario.
  • Necesita que las pruebas sean válidas para el seguro o las fuerzas de seguridad. Deténgase en la instantánea, realice una imagen completa del disco y registre quién la manipuló y en qué momento.

Para un VPS individual que aloja sus propios servicios y no contiene datos de terceros, el procedimiento descrito anteriormente es suficiente. Aísle el servidor desde el panel del proveedor. Tome una instantánea como prueba. Recupere únicamente lo que sea fiable. Rote todas las credenciales. Reinstale desde cero.

FAQ

¿Puedo limpiar un VPS comprometido en lugar de reinstalarlo?

No con garantías, ya que estaría pidiendo al sistema comprometido que se audite a sí mismo. Un ps sustituido oculta un proceso, una línea en /etc/ld.so.preload inyecta código en cada herramienta vinculada dinámicamente que ejecute, y un módulo del kernel puede ocultar archivos a todos los programas simultáneamente. Puede encontrar elementos, por lo que un hallazgo es significativo. No puede demostrar la ausencia, por lo que un resultado "limpio" no es fiable. Limpiar el sistema solo es defendible si el servidor no contiene nada importante y usted acepta que podría volver a ser comprometido.

¿Debo apagar un servidor comprometido o dejarlo encendido?

Primero corte su acceso a la red desde el panel del proveedor, luego déjelo encendido el tiempo suficiente para tomar una instantánea y examinar los procesos en ejecución. Apagarlo destruye la lista de procesos y elimina el registro por completo cuando /var/log/journal no existe, ya que journald escribe en la memoria bajo /run. Apáguelo de todos modos si está atacando activamente otras redes y no tiene forma de bloquear su tráfico saliente. Detener el daño es prioritario frente a conservar las pruebas.

¿Cómo determino cuándo entró el atacante?

Busque la primera línea en Accepted password o Accepted publickey que no pueda explicar, ya sea en /var/log/auth.log o en el journal. Contrástela con un listado de tiempos de cambio, find / -xdev -newerct 'YYYY-MM-DD' -type f, ya que el ctime es más difícil de falsificar que el mtime. Luego, compare ambos con las marcas de tiempo del aviso de abuso de su proveedor, las cuales se registraron fuera de la máquina y no pudieron ser editadas. Elija una copia de seguridad anterior a la más antigua de esas tres fechas. Si nada coincide, asuma que el compromiso es anterior a su historial de copias de seguridad y restaure solo los datos que pueda inspeccionar.

¿Son seguras mis copias de seguridad tras un compromiso?

Los datos suelen serlo, previa inspección. Los archivos del sistema no. Una copia de seguridad realizada después de la intrusión contiene la puerta trasera, por lo que restaurar todo el sistema de archivos raíz restaura también al atacante. Compruebe también el repositorio de copias de seguridad: si las credenciales para acceder a él estaban almacenadas en el servidor comprometido, el historial podría haber sido eliminado o alterado; este es el argumento a favor de destinos de copia de seguridad de solo adición o basados en extracción (pull). Restaure los datos de la aplicación y luego instale el software de nuevo desde los repositorios de la distribución.

¿Debo informar a alguien de que mi VPS fue comprometido?

Responda siempre al aviso de abuso de su proveedor. Más allá de eso, depende de cuyos datos estuvieran en la máquina. Los datos personales pertenecientes a terceros pueden activar una obligación legal de notificación, como el plazo de 72 horas del RGPD ante una autoridad de control. Si se almacenaron credenciales de usuario en el servidor, informe a esos usuarios para que puedan cambiar sus contraseñas en otros servicios. Si las claves en el servidor autorizaban el acceso a sistemas de terceros, como un repositorio de código o una cuenta en la nube, informe a esos proveedores para que puedan verificar si hubo uso indebido. Un servidor puramente personal que no contenga datos de terceros no conlleva ninguna obligación más allá de responder al aviso de abuso.

#security#incident-response#compromise#backups#forensics