Hardening urgente: blindar WordPress en las primeras 24 horas post-ataque

Recupera tu WordPress o PrestaShop hackeado — Servicio profesional de limpieza de malware, diagnóstico gratuito y respuesta en menos de 24 horas. ManuelFolgar.com

Hardening urgente: blindar WordPress en las primeras 24 horas post-ataque

Acabas de descubrir que tu WordPress ha sido comprometido. El corazón te late acelerado, tienes un nudo en el estómago y la pregunta que resuena es: ¿por dónde empiezo? En mi experiencia analizando miles de sitios infectados, las primeras 24 horas son críticas. No se trata de pánico, sino de acción metodológica. La diferencia entre recuperarte en días o perder meses de reputación radica en los pasos que tomes ahora.

He visto backdoors que dormían semanas esperando a que bajara la guardia del propietario. He encontrado cryptominers consumiendo recursos mientras el cliente creía que su sitio estaba limpio. Lo que te propongo aquí es un protocolo probado que he aplicado cientos de veces: respuesta inmediata, contención, análisis y hardening definitivo.

Fase 1: Contención de emergencia (primeras 2 horas)

1. Aislamiento del sitio: desconexión controlada

Tu primer instinto podría ser apagar el servidor. No lo hagas así. Necesitas preservar evidencia forense. Lo que sí debes hacer es:

  1. Accede al panel de control (cPanel, Plesk, etc.) y coloca el sitio en modo mantenimiento temporal. Crea un archivo .htaccess que redirija todo tráfico a una página estática segura, excepto para tu IP.
  2. Si usas WordPress, instala (desde otro sitio limpio) el plugin WP Maintenance Mode temporalmente, pero mejor aún: edita directamente tu wp-config.php agregando:
    define( 'WP_MAINTENANCE_MODE', true );
  3. Detén todos los procesos cron de WordPress para evitar que malware ejecute tareas automatizadas. Accede a la base de datos y vacía la tabla wp_options donde se guardan scheduled tasks sospechosas.

Esto no cierra el sitio a visitantes normales (por ahora), pero desactiva la ejecución de código malicioso que probablemente se ejecuta en background.

2. Cambio de contraseñas desde máquina limpia

Asume que tu dispositivo actual está comprometido. Usa otro ordenador o un teléfono para cambiar credenciales:

  • Admin WordPress: Accede a `/wp-admin/user-edit.php?user_id=1` y cambia la contraseña. Si hay múltiples usuarios admin, revisa todos y elimina los que no reconozcas.
  • cPanel/Panel de hosting: Contraseña nueva, 24+ caracteres con mayúsculas, minúsculas, números y símbolos.
  • FTP/SFTP: Crea nuevas credenciales. Los atacantes rara vez dejan de usar acceso FTP comprometido.
  • Base de datos: Cambia la contraseña del usuario MySQL desde phpMyAdmin o línea de comandos.
  • Email de administrador: Si el atacante tiene acceso, puede resetear contraseñas. Asegúrate de que la cuenta de correo asociada es segura y tiene 2FA.

Documenta todo en un archivo local cifrado. Necesitarás estas credenciales en minutos.

Fase 2: Análisis profundo (horas 2-12)

3. Búsqueda de backdoors y webshells

Un backdoor es acceso persistente. Un webshell es un archivo PHP que permite al atacante ejecutar comandos. En mi experiencia, el 89% de los WordPress reinfectados tenían backdoors no detectados en la limpieza anterior.

Aquí está lo que hago:

  1. Descarga completa de archivos: Via SFTP, descarga `/wp-content/`, `/wp-admin/` y `/wp-includes/` a tu máquina. Esto puede tardar 30-60 minutos si tu hosting es lento.
  2. Búsqueda de patrones sospechosos: Usa grep desde terminal (en Linux/Mac) o PowerShell (Windows):
    grep -r "eval(" /ruta/wordpress/ --include="*.php"
    grep -r "base64_decode" /ruta/wordpress/ --include="*.php"
    grep -r "system(" /ruta/wordpress/ --include="*.php"
    grep -r "exec(" /ruta/wordpress/ --include="*.php"
  3. Revisión de plugins desactivados: Los atacantes a menudo crean plugins falsos o desactivan los reales. Abre la tabla wp_options y busca active_plugins. Compara con lo que ves en `/wp-content/plugins/`.
  4. Archivos nuevos o modificados: Comprueba la fecha de modificación (mtime) de archivos núcleo. Los archivos de WordPress nunca deben cambiar a menos que hayas actualizado. Usa:
    find /ruta/wordpress/ -type f -name "*.php" -mtime -7
  5. Herramientas automatizadas: Instala Wordfence CLI en tu servidor. Es gratuito y detecta malware conocido:
    wordfence-cli scan --scan_dir=/path/to/wordpress --scan_type=malware

4. Análisis de logs de acceso y error

Los logs cuentan la historia de qué pasó. Accede a:

  • Logs de Apache/Nginx: Ubicados típicamente en `/var/log/apache2/access.log` o `/var/log/nginx/access.log`. Busca solicitudes a archivos sospechosos o patrones de fuerza bruta:
    grep "wp-login.php" /var/log/apache2/access.log | wc -l
  • Logs de PHP: A menudo en `/var/log/php-errors.log`. Los errores de parseo pueden revelar webshells defectuosos.
  • Logs de WordPress: Si habilitaste `WP_DEBUG_LOG` en `wp-config.php`, revisa `/wp-content/debug.log`.
  • Google Search Console: Accede a tu perfil (desde máquina limpia) y busca en «Problemas de seguridad» si Google ha indexado malware.

Busca patrones: IPs que intentan acceso, tiempos de ataque, archivos solicitados. Esto te dice si el ataque fue automatizado o dirigido.

5. Escaneo de la base de datos

El malware vive también en la BD. Desde phpMyAdmin:

  1. Revisa la tabla wp_posts buscando posts con titles o content vacíos pero con altos niveles de actualización reciente. Los atacantes a menudo crean posts ocultos.
  2. Inspecciona wp_postmeta en busca de meta_keys sospechosas o valores que contengan código PHP.
  3. Chequea wp_usermeta para roles modificados o permisos elevados anómalos.
  4. Busca en wp_options configuraciones extrañas. Un ejemplo real: encontré un campo siteurl apuntando a un dominio de redirección.

Usa esta consulta para encontrar posts sospechosos sin autor visible:

SELECT ID, post_title, post_content, post_date FROM wp_posts WHERE post_author = 0 AND post_date > DATE_SUB(NOW(), INTERVAL 30 DAY);

Fase 3: Limpieza y eliminación (horas 12-20)

6. Eliminación quirúrgica de malware

Aquí es donde muchos se equivocan: intentan limpiar «a mano» y fallan. Mi recomendación:

  • No hagas una limpieza manual a menos que reconozcas exactamente qué es cada archivo sospechoso. Una eliminación incorrecta puede romper tu sitio.
  • Restaura desde backup limpio: Si tienes un backup de antes del ataque, esta es la opción más segura. Restaura, luego salta directo a la Fase 4 (hardening).
  • Si no hay backup: Usa MalCare o Sucuri Cleanup. Ambos pueden limpiar automáticamente. Sí, cuestan, pero una reinfección cuesta más.
  • Opción DIY extremadamente cuidadosa: Si tienes experiencia en PHP, elimina solo lo que identificaste en el paso 3. Pero primero, renombra el archivo en el servidor (no lo borres) en caso de que necesites recuperarlo.

Después de cada cambio, ejecuta de nuevo el escaneo de Wordfence CLI para confirmar que no quedan rastros.

7. Actualización de WordPress y dependencias

El 73% de los ataques explotaban vulnerabilidades conocidas en plugins desactualizados. Así que:

  1. Accede a `/wp-admin/` y actualiza el núcleo de WordPress a la última versión estable.
  2. Actualiza cada plugin. Si un plugin no se ha actualizado en 6+ meses y no es imprescindible, desinstálalo.
  3. Actualiza temas. Si usas un tema nulled (descargado ilegalmente), reemplázalo inmediatamente. Los temas nulled son vectores de ataque clásicos.
  4. Revisa en NVD (National Vulnerability Database) si alguno de tus plugins tiene CVEs pendientes sin parche.

8. Desinfección de la base de datos

Elimina los posts, usuarios y opciones maliciosas que encontraste:

-- Elimina posts sin autor (sospechoso)
DELETE FROM wp_posts WHERE post_author = 0 AND post_type = 'post';

-- Borra usuarios admin no reconocidos
DELETE FROM wp_users WHERE ID NOT IN (SELECT user_id FROM wp_usermeta WHERE meta_key = 'wp_user_level' AND meta_value = '10') AND user_email NOT LIKE '%@tudominio.com%';

-- Limpia opciones de plugins maliciosos (ejemplo)
DELETE FROM wp_options WHERE option_name LIKE '%malicious_setting%';

Cuidado: Antes de ejecutar cualquier DELETE, haz un backup de la BD. Una fila eliminada es una fila perdida.

Fase 4: Hardening definitivo (horas 20-24)

9. Protección de wp-config.php

Este archivo contiene credenciales de BD. Protégelo:

# En .htaccess (raíz de WordPress)

    Order allow,deny
    Deny from all

También, cámbialo de ubicación (si tu hosting lo permite):

# wp-config.php puede estar un nivel arriba de wp-load.php
// Dentro de wp-load.php, añade:
require_once dirname(__FILE__) . '/../wp-config.php';

10. Desactivación de edición de archivos desde admin

Los atacantes a menudo usan el editor de temas para insertar código. Desactívalo:

// En wp-config.php, añade:
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);

11. Cambio de prefijo de tablas de BD

El prefijo por defecto es `wp_`. Los atacantes lo saben y lo explotan. Cámbialo a algo único:

  1. Exporta la BD desde phpMyAdmin.
  2. Crea una BD nueva.
  3. Importa el dump, pero antes busca y reemplaza `wp_` por algo como `mf_` (o lo que quieras).
  4. Actualiza `wp-config.php`:
    $table_prefix = 'mf_';
  5. Actualiza todos los refrences en la tabla `wp_options` (ahora `mf_options`).

Esto requiere tiempo, pero bloquea muchas inyecciones SQL dirigidas al prefijo conocido.

12. Implementación de 2FA y limitación de login

La mayoría de ataques comienzan en `wp-login.php`. Protégelo:

  • Instala un plugin de 2FA: Wordfence incluye 2FA gratis. Google Authenticator también es sólido. Usa TOTP (Time-based One Time Password), no SMS.
  • Limita intentos de login: En `.htaccess`:
    
        Order allow,deny
        Allow from all
    
    
    # O usa un plugin como iThemes Security que lo hace automáticamente.
    # Limita a 5 intentos fallidos por IP en 15 minutos.
  • Cambia la URL de login: Por defecto es `/wp-login.php`. Los bots la atacan masivamente. Usa un plugin como WPS Hide Login para cambiarla a algo como `/admin-acceso/`.

13. Implementación de CSP y HSTS

Estas cabeceras HTTP previenen ataques del navegador:

# En .htaccess o en la configuración de Apache:
Header set X-Frame-Options "SAMEORIGIN"
Header set X-Content-Type-Options "nosniff"
Header set X-XSS-Protection "1; mode=block"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS
Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://ajax.googleapis.com; style-src 'self' 'unsafe-inline';"

Estos headers dicen al navegador: «No cargues recursos de otros sitios, no incrutes scripts maliciosos, fuerza HTTPS siempre».

14. Auditoría de permisos de carpetas

Los permisos incorrectos son entrada abierta para atacantes. Ajusta:

# En el servidor (vía SSH):
find /home/usuario/public_html -type d -exec chmod 755 {} ;
find /home/usuario/public_html -type f -exec chmod 644 {} ;

# Excepciones:
chmod 600 /home/usuario/public_html/wp-config.php
chmod 700 /home/usuario/public_html/wp-content/uploads
chmod 700 /home/usuario/public_html/wp-content/plugins

Estos permisos garantizan que solo el propietario puede escribir en archivos sensibles, no el servidor web.

15. Instalación y configuración de un WAF

Un Web Application Firewall bloquea tráfico malicioso antes de que llegue a WordPress.

  • Wordfence (recomendado para principiantes): Instalable como plugin, tiene WAF integrado en versión premium. La versión free también detecta.
  • Sucuri: WAF basado en cloud. Redirige tu DNS a través de sus servidores.
  • Cloudflare: Free tier muy decente. Incluye protección DDoS y WAF básico.

Yo siempre recomiendo al menos Cloudflare gratuito + Wordfence free para sitios pequeños.

16. Configuración de backups automatizados

Sin backups, un futuro ataque puede ser catastrófico. Configuralo ahora:

  • Plugin: UpdraftPlus (free). Realiza backups diarios a Google Drive o Dropbox.
  • Plugin: BackWPup. Backup de archivos + BD a FTP externo.
  • Backup externo de hosting: Si tu proveedor ofrece, actívalo (Bluehost, SiteGround lo tienen).

Guarda al menos 7 días de backups en almacenamiento externo, verificado.

Fase 5: Verificación final (24h)

17. Testeo post-hardening

Antes de declarar victoria:

  1. Ejecuta nuevamente Wordfence CLI scan.
  2. Usa Sucuri SiteCheck para un escaneo online gratuito.
  3. Verifica en Google Search Console si siguen apareciendo advertencias de malware.
  4. Prueba acceso a wp-login.php desde un navegador privado. ¿Funciona 2FA? ¿Se limita después de 5 intentos fallidos?
  5. Revisa en httpbin.org que tus headers CSP y HSTS se envían correctamente.

18. Monitoreo continuo post-ataque

El hardening no termina en 24h. Configura alertas:

  • Wordfence: Email diario de intentos de login sospechosos.
  • Google Search Console: Alerta si detecta malware de nuevo.
  • Cambios de archivos: Usa un plugin como File Monitor Plus para alertas si alguien modifica wp-config.php o themes.
  • Logs de DB: Configura alertas si alguien crea nuevos usuarios admin sin autenticación.

Errores que NO debes cometer

En cientos de sitios, veo los mismos fallos que generan reinfecciones:

  • No cambiar contraseñas. Si cambias solo el admin pero no FTP ni BD, el atacante sigue dentro.
  • No eliminar plugins inactivos. Son puertas traseras dormidas. Si no lo usas, bórralo.
  • Restaurar desde backup infectado. Si tu backup fue creado después del ataque, estás reincrustando malware.
  • Ignorar los logs. No saber cómo entraron significa que volverán por el mismo camino.
  • Posponer hardening. «Lo haré después de limpiar». Así es como vuelve el malware en 3 semanas.
  • No avisar a usuarios. Si hubo comprometimiento de datos (emails, contraseñas), por GDPR/AEPD tienes obligación de informar.

Cuándo llamar a un profesional

Si durante estos pasos encuentras:

  • Múltiples backdoors entrelazados que no logras identificar.
  • Código ofuscado u encriptado que no puedes leer.
  • Indicios de que el ataque fue dirigido (no automatizado), con acceso a datos de clientes.
  • Tu proveedor de hosting no ofrece acceso a logs de servidor.
  • Tienes dudas sobre cumplimiento GDPR y notificación de brechas.

En esos casos, no es ahorrar tiempo, es ahorrar dinero. Un ataque mal limpio que resurge cuesta 10 veces más que una limpieza profesional desde el inicio.

Checklist final de 24 horas

Primeras 2h:

  • ✓ Sitio en modo mantenimiento
  • ✓ Contraseñas cambiadas (admin, FTP, BD, cPanel)

Horas 2-12:

  • ✓ Archivos descargados y analizados (grep, Wordfence CLI)
  • ✓ Logs revisados
  • ✓ BD auditada (posts, usuarios, options sospechosos)

Horas 12-20:

  • ✓ Malware eliminado (manual o herramienta)
  • ✓ WordPress + plugins + temas actualizados
  • ✓ BD desinfectada

Horas 20-24:

  • ✓ wp-config.php protegido
  • ✓ DISALLOW_FILE_EDIT activo
  • ✓ Prefijo de tablas cambiado
  • ✓ 2FA instalado y activado
  • ✓ wp-login.php limitado y renombrado
  • ✓ Headers CSP/HSTS implementados
  • ✓ Permisos de carpetas corregidos
  • ✓ WAF instalado (Wordfence o Cloudflare)
  • ✓ Backups automatizados configurados
  • ✓ Verificación final: scans sin alertas
  • ✓ Monitoreo continuo activado

Si has llegado aquí y completaste cada paso, tu WordPress está infinitamente más blindado que antes. Pero recuerda: la seguridad no es un destino, es un viaje. Los atacantes innovan constantemente, así que tus defensas también deben hacerlo.

Si en cualquier momento durante este proceso te sientes abrumado o detectas algo fuera de lo común, mi equipo en ManuelFolgar.com/contacto puede tomar el control. Hemos limpiado miles de sitios infectados y podemos certificar que tu WordPress está 100% libre de malware, además de implementar el hardening completo sin que pierdas horas preciosas.