Archivo
Archivo
Etiquetas
Etiquetas
Entradas populares de este blog
Listado de palabras en castellano
PHP Non-Thread Safe vs Thread Safe
Recuperar y migrar un WordPress comprometido
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Hace unos días tuve que migrar un WordPress a un servidor nuevo después de que el anterior quedara comprometido. Cuando llegas a un punto en el que faltan binarios del sistema, hay procesos extraños o cron jobs que no reconoces, seguir intentando limpiar la máquina deja de tener sentido. En estos casos prefiero recuperar los datos necesarios y reconstruir el servidor desde cero. Este fue exactamente el proceso que seguí.
1. Recuperar el WordPress del servidor antiguo
Lo primero fue sacar la carpeta completa del WordPress.
En mi caso estaba en:
/var/www/html/wordpressDesde mi máquina local ejecuté:
scp -r root@<server_ip>:/var/www/html/wordpress .Con esto copié todo el código del sitio a mi máquina local.
2. Recuperar la base de datos
Para identificar la base de datos revisé el wp-config.php:
grep DB_ wordpress/wp-config.phpUna vez identificado el nombre de la base de datos y el usuario, generé el dump.
mysqldump --no-tablespaces -u wordpress_user -p wordpress_db > /root/wordpress_no_tablespaces.sqlTuve que usar --no-tablespaces porque el usuario no tenía permisos PROCESS.
Después lo copié a local:
scp root@<server_ip>:/root/wordpress_no_tablespaces.sql .3. Recuperar configuración del servidor
También guardé algunas configuraciones del servidor antiguo por si necesitaba replicar algo.
nginx
scp -r root@<server_ip>:/etc/nginx ./backup_server/PHP
scp -r root@<server_ip>:/etc/php ./backup_server/certificados SSL
scp -r root@<server_ip>:/etc/letsencrypt ./backup_server/logs
scp -r root@<server_ip>:/var/log/nginx ./backup_server/Al final terminé con esta estructura:
wordpress/
wordpress_no_tablespaces.sql
backup_server/nginx
backup_server/php
backup_server/letsencrypt
backup_server/logs4. Probar el WordPress en local con Docker
Antes de restaurar nada en un servidor nuevo preferí comprobar que el backup funcionaba correctamente y que no había nada extraño en el código. Para hacerlo monté un entorno local con Docker.
La idea era reproducir el stack del servidor:
nginx
php-fpm
mysql
Primero construí el entorno:
docker compose up -d --buildLuego importé la base de datos dentro del contenedor:
docker exec -i wp_db mysql -u root -pwordpress_root_password wordpress_db < wordpress_no_tablespaces.sqlDespués accedí al WordPress desde el navegador:
http://localhostEsto me permitió comprobar:
que el sitio cargaba correctamente
que la base de datos estaba intacta
que los plugins funcionaban
que no había código sospechoso
Además ejecuté algunas comprobaciones básicas.
Buscar PHP en uploads:
find wordpress/wp-content/uploads -name "*.php"Buscar funciones sospechosas:
grep -R "base64_decode(" wordpressUna vez comprobado que todo funcionaba correctamente continué con la migración.
5. Montar un servidor nuevo
Con el backup verificado monté un servidor nuevo con Ubuntu 24.04.
Actualicé el sistema:
apt update
apt upgrade -y6. Instalar el stack del servidor
Ubuntu 24.04 instala PHP 8.3 por defecto, pero en mi caso quería utilizar PHP 8.4, así que añadí el repositorio de PHP mantenido por Ondřej Surý.
Primero instalé las herramientas necesarias:
apt install -y software-properties-commonDespués añadí el repositorio:
add-apt-repository ppa:ondrej/php
apt updateUna vez añadido el repositorio instalé nginx, MySQL y PHP 8.4 con las extensiones necesarias para WordPress:
apt install -y nginx mysql-server php8.4-fpm php8.4-mysql php8.4-cli php8.4-curl php8.4-gd php8.4-mbstring php8.4-xml php8.4-zip php8.4-intl unzip certbot python3-certbot-nginx fail2banDespués comprobé la versión de PHP instalada:
php -vLa salida debería mostrar algo similar a:
PHP 8.4.x (cli)También verifiqué que el socket de PHP-FPM estaba disponible:
ls /run/php/Debería aparecer:
php8.4-fpm.sockEste es el socket que luego se utiliza en la configuración de nginx.
7. Crear la base de datos
Entré en MySQL:
mysqlCreé la base de datos y el usuario:
CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wordpress_user'@'localhost' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;8. Subir el dump al servidor nuevo
Desde mi máquina local:
scp wordpress_no_tablespaces.sql root@<new_server_ip>:~Importé la base de datos:
mysql -u wordpress_user -p wordpress < ~/wordpress_no_tablespaces.sql9. Subir el WordPress
scp -r wordpress/* root@<new_server_ip>:/var/www/<domain>Permisos correctos:
chown -R www-data:www-data /var/www/<domain>10. Configurar nginx
Creé el virtual host:
nano /etc/nginx/sites-available/<domain>Configuración básica:
server {
listen 80;
server_name <domain>;
root /var/www/<domain>;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}
}Activé el sitio:
ln -s /etc/nginx/sites-available/<domain> /etc/nginx/sites-enabled/11. Activar HTTPS
certbot --nginx -d <domain>12. Comprobaciones finales
Verificar PHP en uploads:
find /var/www/<domain>/wp-content/uploads -name "*.php"Comprobar cronjobs:
crontab -l
ls /etc/cron*Verificar renovación SSL:
certbot renew --dry-runConclusión
Cuando un servidor ha sido comprometido realmente, la forma más rápida de volver a tener control sobre el sistema es reconstruir el entorno desde cero.
En mi caso el proceso fue:
recuperar WordPress y base de datos
validar el backup en Docker
montar un servidor limpio
restaurar el sitio
Puede parecer más trabajo que intentar limpiar el servidor original, pero a largo plazo suele ser mucho más seguro.
Comentarios