¿Por qué WordPress es tan atacado?
WordPress alimenta el 43% de todos los sitios web del mundo. Esa popularidad lo convierte en el objetivo principal de hackers automatizados que escanean millones de sitios buscando versiones desactualizadas y plugins vulnerables. La buena noticia: el 90% de los hackeos son prevenibles con configuración correcta.
Actualización: la defensa más importante
La causa número uno de hackeos en WordPress es software desactualizado. Activa las actualizaciones automáticas para WordPress core, plugins y temas en wp-config.php:
define('WP_AUTO_UPDATE_CORE', true);
add_filter('auto_update_plugin', '__return_true');
add_filter('auto_update_theme', '__return_true');
Proteger wp-admin
Cambia la URL de login de /wp-admin a algo personalizado con el plugin WPS Hide Login. Limita los intentos fallidos de login con Limit Login Attempts Reloaded. Implementa autenticación de dos factores con Google Authenticator.
Permisos de archivos correctos
# Directorios: 755
find /var/www/html -type d -exec chmod 755 {} \;
# Archivos: 644
find /var/www/html -type f -exec chmod 644 {} \;
# wp-config.php: 600 (solo lectura del propietario)
chmod 600 wp-config.php
Hardening de wp-config.php
Mueve wp-config.php un directorio arriba de la raíz web. Agrega estas líneas de seguridad:
define('DISALLOW_FILE_EDIT', true); // Deshabilita editor de temas/plugins
define('DISALLOW_FILE_MODS', true); // Deshabilita instalación de plugins
define('FORCE_SSL_ADMIN', true); // Fuerza HTTPS en admin
define('WP_DEBUG', false); // Nunca en producción
Plugins de seguridad esenciales
Wordfence Security: Firewall de aplicación web, escáner de malware, y monitoreo en tiempo real. La versión gratuita es suficiente para la mayoría de sitios.
UpdraftPlus: Backups automáticos a Google Drive, Dropbox o Amazon S3. Configura backups diarios y guarda los últimos 30 días.
Really Simple SSL: Fuerza HTTPS en todo el sitio y gestiona los headers de seguridad.
Headers de seguridad HTTP
Agrega estos headers en tu .htaccess o configuración de Nginx:
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'