secaudit.eu
Incidentes

Redirección maliciosa en WordPress: encontrar y eliminar

Redirección maliciosa en WordPress: reprodúzcala con curl y las herramientas de desarrollo, localícela en .htaccess, PHP, base de datos o CDN y evite que vuelva.

Por , AngelForce OÜ 9 min de lectura

También en: English Deutsch Français Italiano Polski Português Türkçe

Una redirección maliciosa en WordPress está diseñada para que usted, el propietario, no la vea. El código comprueba quién visita la web y redirige solo a algunas personas: usuarios de móvil, visitantes que llegan desde Google o desde redes sociales y, a menudo, cada visitante una sola vez. Casi siempre se salta a propósito a los usuarios con sesión iniciada y a los administradores.

Por eso, si un cliente le dice «su web me ha llevado a una página falsa de premios» y en su portátil todo se ve normal, créale al cliente. Los destinos suelen ser páginas de estafa, sorteos falsos, redes publicitarias agresivas o descargas de malware. Google puede marcar el sitio y los visitantes dejan de fiarse. Las redirecciones son solo uno de los síntomas; los demás se tratan en 12 señales de que su sitio WordPress ha sido hackeado.

Por qué el propietario nunca ve la redirección maliciosa

Las condiciones son sencillas y eficaces. El código lee la cabecera User-Agent para detectar móviles y la cabecera Referer para detectar tráfico de buscadores. También comprueba si existe la cookie de inicio de sesión de WordPress. Tras la primera redirección, crea su propia cookie o registra la dirección IP para no redirigir otra vez a la misma persona.

Esa combinación explica casi todos los casos de «no consigo reproducirlo». Usted tiene la sesión iniciada, navega desde un ordenador, escribe la dirección directamente y quizá ya lo hayan redirigido una vez. Cualquiera de esas condiciones basta para apagar la redirección.

Diagrama: las capas donde puede esconderse una redirección de spam, desde la caché del CDN hasta el JavaScript inyectado en el navegador
Una petición atraviesa varias capas. Cada una puede contener una redirección, y el tipo de respuesta indica en qué parte de la pila buscar.

Reproduzca la redirección de forma segura

Antes de rastrear archivos, averigüe qué tipo de redirección tiene delante. El tipo de respuesta le dice en qué capa buscar.

Empiece por el navegador. Abra una ventana privada y asegúrese de no tener la sesión iniciada. Abra las herramientas de desarrollo (F12 en Chrome, Edge y Firefox) y active la barra de dispositivos (Ctrl+Shift+M) para emular un teléfono. En la pestaña Network (Red), marque Preserve log (Conservar registro); en Firefox, la opción se llama Persist Logs y está en el menú de ajustes de Network. Así las entradas se conservan al cambiar de página. Para obtener un referente real de Google, busque su propio dominio en Google y haga clic en el resultado.

Ahora mire la primera entrada de la pestaña Network:

  • **Estado 301, 302, 307 o 308 con un Location ajeno**: la redirección ocurre en el servidor. Eso incluye el CDN, las reglas del servidor web, PHP y el propio WordPress.
  • Estado 200 y después una petición a un dominio ajeno: la página cargó con normalidad y luego JavaScript (o una etiqueta meta refresh) sacó al navegador de ella. Busque script inyectado.

Después confirme el resultado con curl. Curl no ejecuta JavaScript y no sigue redirecciones salvo que se lo indique. El siguiente comando hace una petición GET normal e imprime solo las cabeceras de la respuesta; evite curl -I, porque parte del código inyectado ignora las peticiones HEAD:

curl -s -o /dev/null -D - \
  -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1" \
  -e https://www.google.com/ \
  https://example.com/

Una línea Location: que apunta a un dominio desconocido confirma una redirección en el servidor. Si la línea de estado muestra 200, descargue el cuerpo de la página y busque en él código de redirección y ofuscación:

curl -s -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X)" \
  -e https://www.google.com/ https://example.com/ \
  | grep -Eio 'window\.location|location\.href|location\.replace|http-equiv=.?refresh|atob\(|eval\(|fromCharCode|script[^>]+src="[^"]+"'

Repita la prueba sin -A ni -e y compare los resultados. Luego pruebe varias URL: una entrada del blog, una página de producto y la página de contacto. Muchas inyecciones solo afectan a algunas plantillas.

Un resultado limpio no demuestra que el sitio lo esté. Si el código redirige a cada IP una sola vez o solo apunta a determinados países, su prueba puede no detectarlo. Repita la prueba desde otra red, por ejemplo con un teléfono con datos móviles.

Redirecciones en el servidor: .htaccess, configuración y PHP que se ejecuta primero

Si curl muestra un 3xx hacia un dominio ajeno, revise el servidor y el código que se ejecuta antes de que WordPress genere nada.

En Apache, compruebe todos los archivos .htaccess, no solo el de la raíz web. Busque condiciones de reescritura sobre el user agent o el referente, y la directiva auto_prepend_file, que hace que PHP cargue un archivo del atacante antes de cada petición:

grep -rn --include=.htaccess -E "HTTP_(USER_AGENT|REFERER)|auto_prepend_file" .
grep -rn --include=.user.ini --include=php.ini "auto_prepend_file" .

Existen líneas RewriteCond %{HTTP_USER_AGENT} legítimas, por ejemplo en algunos plugins de caché. Una regla que envía tráfico móvil o procedente de Google a un dominio que usted no reconoce no es legítima.

A continuación, liste los archivos PHP y de configuración modificados recientemente. Los atacantes pueden restablecer las marcas de tiempo, así que trate esta lista como punto de partida, no como prueba. Ejecute esto desde la raíz de WordPress:

find . -type f \( -name "*.php" -o -name ".htaccess" -o -name ".user.ini" \) -mtime -14 -print

Examine con atención cualquier añadido al principio o al final de wp-config.php y todos los archivos de wp-content/mu-plugins. Los plugins de uso obligatorio (must-use) se cargan automáticamente y no aparecen en la lista normal de plugins. Revise también el functions.php del tema activo. Después ejecute wp core verify-checksums para detectar archivos del núcleo modificados. Para interpretar su resultado y reinstalar el núcleo con seguridad, consulte nuestra guía sobre cómo verificar los checksums de WordPress.

En nginx, las reglas están en la configuración del servidor, no en .htaccess. En un alojamiento gestionado puede que no pueda verlas. En ambos casos, pida a su proveedor de hosting que revise las reglas de redirección y los ajustes de prepend a nivel de servidor.

Las opciones siteurl y home

Una variante distinta y más burda modifica las opciones siteurl y home. Entonces WordPress redirige a todos los visitantes, usted incluido, al dominio del atacante. Compruebe ambos valores:

wp option get siteurl
wp option get home

Sin WP-CLI, abra phpMyAdmin y consulte la tabla wp_options. Su prefijo de tablas puede ser distinto de wp_, así que verifique $table_prefix en wp-config.php. Para corregir los valores:

wp option update siteurl 'https://example.com'
wp option update home 'https://example.com'

Ejecute también grep -n "WP_HOME\|WP_SITEURL" wp-config.php. Si esas constantes están definidas, anulan los valores de la base de datos. Un atacante puede haberlas colocado ahí, y entonces su corrección en la base de datos parecerá no surtir efecto.

Redirecciones con JavaScript en entradas, widgets, archivos del tema y scripts de cabecera

Una respuesta 200 seguida de un salto a otro dominio significa que hay un script ejecutándose en la página. Puede proceder de varios sitios:

  • Contenido de entradas: etiquetas script inyectadas en post_content, a menudo en decenas de entradas a la vez.
  • Opciones: filas de widgets (widget_*), opciones del tema y ajustes de constructores de páginas en wp_options.
  • Ajustes de «insertar cabeceras y pies»: los plugins de fragmentos de código y los constructores de páginas guardan ahí scripts para todo el sitio. A un atacante con acceso de administrador le basta con pegar una línea.
  • Archivos del tema y de plugins: header.php, footer.php y archivos JavaScript encolados.

Una búsqueda rápida en la base de datos (cambie wp_posts si su prefijo de tablas es distinto):

wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%script%src=%';"
wp db search 'fromCharCode' --all-tables
wp option list --search='widget_*' --fields=option_name

Cuente con encontrar ofuscación. El código inyectado rara vez contiene la URL de destino en texto plano. Busque atob(, cadenas largas en base64, String.fromCharCode y orígenes de script que imitan dominios conocidos de CDN o de analítica con una ortografía ligeramente distinta. La técnica de búsqueda en la base de datos y la limpieza se explican con más detalle en spam SEO en WordPress.

Copias en caché: plugins de caché, caché del servidor y CDN

Puede dejar limpio el origen por completo y que los visitantes sigan siendo redirigidos, porque la página infectada sigue almacenada en algún sitio. Las copias pueden sobrevivir en los archivos de caché de página (wp-content/cache), en una caché de objetos como Redis o Memcached, en la caché del servidor de su hosting y en los servidores de borde del CDN.

Purgue siguiendo el orden de la petición, del origen hacia fuera:

  1. Termine de limpiar archivos y base de datos en el origen.
  2. Vacíe la caché de páginas del plugin de caché.
  3. Vacíe la caché de objetos con wp cache flush.
  4. Purgue la caché del servidor desde el panel del hosting.
  5. Purgue todo en el CDN.
  6. Repita la prueba con los comandos curl anteriores, con y sin el user agent móvil y el referente de Google.

Considere también el caso inverso: que alguien haya creado la redirección en el CDN o en el DNS. Quien tenga acceso a su cuenta del CDN puede crear una regla de redirección sin tocar WordPress. Revise las reglas de redirección y de página en el panel del CDN, así como sus registros DNS. Compruebe quién tiene acceso a esas cuentas y retire el de las personas que ya no lo necesitan.

Encuentre el punto de entrada o la redirección volverá

La redirección es la carga útil, no la brecha. Si solo elimina la carga útil, lo normal es que vuelva en unos días, porque la vía de entrada sigue abierta. Los puntos de entrada más habituales son plugins vulnerables o «nulled» (versiones pirata), credenciales de administrador o de hosting robadas, web shells en wp-content/uploads y puertas traseras que quedaron y reinyectan el código mediante una tarea cron o una opción de la base de datos.

Una primera comprobación breve:

  • Administradores desconocidos: wp user list --role=administrator
  • Contraseñas de aplicación que usted no creó (Usuarios > Perfil)
  • Eventos programados que no reconoce: wp cron event list
  • Archivos PHP en uploads: find wp-content/uploads -name "*.php"
  • Plugins y temas desactualizados o «nulled»

Una vez cerrada la brecha, cambie las contraseñas de administrador, hosting, base de datos, SFTP y CDN. Después rote las claves de seguridad (salts) con wp config shuffle-salts. Esto cierra la sesión de todos los usuarios. Siga el plan completo de eliminación de malware en WordPress para la conservación de pruebas y la decisión entre limpiar o restaurar.

Es posible que el atacante también haya podido leer datos de clientes, envíos de formularios de contacto o pedidos. En ese caso, evalúe el incidente como una posible violación de la seguridad de los datos personales. Consulte la notificación de brechas del RGPD en 72 horas.

FAQ

¿Por qué solo se redirige a los usuarios de móvil?

Los visitantes desde el teléfono se fijan menos en una dirección extraña y es más probable que pulsen en páginas de estafa. Además, los propietarios suelen revisar su web desde un ordenador y con la sesión iniciada. La condición de «solo móvil» existe para ocultarle la redirección a usted.

Google muestra «Es posible que este sitio haya sido pirateado». ¿Qué hago?

Primero limpie el sitio, cierre el punto de entrada y purgue todas las cachés. Después solicite una revisión en Google Search Console. El proceso se describe en spam SEO en WordPress. Si pide la revisión antes de que la redirección haya desaparecido de verdad, lo normal es que se rechace.

¿Puede un plugin de seguridad eliminar la redirección por mí?

Los escáneres ayudan a encontrarla, pero no sustituyen la limpieza manual ni la búsqueda del punto de entrada. El plugin de auditoría de secaudit.eu comprueba la integridad de los archivos frente a una referencia base y señala indicios de compromiso como administradores ocultos, eventos cron sospechosos y spam en la base de datos. También busca spam SEO oculto. Detecta e informa. Eliminar el código y cerrar la brecha es cosa suya o de un profesional al que contrate.

Compruebe su propio sitio

Security Audit & Compliance es el plugin de WordPress de secaudit.eu: busca malware, spam oculto, archivos del núcleo modificados y código vulnerable, y relaciona sus hallazgos con el art. 32 del RGPD, el art. 21 de NIS2 y el OWASP Top 10.

Ver qué comprueba el plugin
Melike Görel

Melike Görel escribe las guías de secaudit.eu sobre seguridad de WordPress y cumplimiento normativo europeo para AngelForce OÜ, la empresa de software de Tallin que está detrás de secaudit.eu.

Elaborado con ayuda de IA y verificado antes de su publicación. Este artículo es información general, no asesoramiento jurídico.