Comment détecter les portes dérobées dissimulées dans WordPress avec WP-CLI et SQL
2026년 7월 30일
0
Internet TechnologyComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
Appuyer sur le bouton de mise à jour du cœur d'un site WordPress réalisé par un prestataire extérieur fait toujours hésiter. De peur qu'un conflit avec le thème ou un extension personnalisée ne provoque un écran blanc, on repousse l'échéance, et le site se retrouve rapidement truffé de vulnérabilités. Lorsque l'angoisse d'avoir déjà été piraté vous envahit, voici la procédure de contrôle pratique la plus rapide pour inspecter la base de données et le serveur.
En général, un attaquant s'introduit discrètement. Il modifie directement la table wp_usermeta de la base de données pour accorder subrepticement les privilèges d'administrateur à un compte existant. Bien que cela n'apparaisse pas forcément dans la liste classique des utilisateurs, une requête directe dans la base de données les démasque immédiatement.
`sql
SELECT
u.ID,
u.user_login,
u.user_email,
u.user_registered,
m.meta_value AS capabilities
FROM
wp_users u
INNER JOIN
wp_usermeta m ON u.ID = m.user_id
WHERE
m.meta_key = 'wp_capabilities'
AND (
m.meta_value LIKE '%"administrator"%'
OR m.meta_value LIKE '%"administrator":true%'
)
ORDER BY
u.user_registered DESC;
`
Vient ensuite le système de fichiers. Si des fichiers PHP traînent dans le dossier wp-content/uploads, qui ne devrait contenir que des images ou des documents, il s'agit neuf fois sur dix d'une porte dérobée (backdoor). Ouvrez un terminal SSH et balayez le répertoire à la recherche de fichiers dangereux.
`bash
find wp-content/uploads/ -type f -name "*.php" -ls
find . -type f -name "*.php" -exec grep -HnE "(eval(|base64_decode(|gzinflate(|passthru(|shell_exec()" {} ;
wp core verify-checksums --include-root
`
Il faut également analyser les journaux d'accès. Les attaques ciblant l'API REST génèrent généralement un grand nombre de requêtes POST en très peu de temps et obtiennent des réponses 200 ou 201. Extrayez les requêtes ayant reçu une réponse suspecte dans le fichier access.log de Nginx.
`bash
grep -E "POST|PUT" /var/log/nginx/access.log | grep -E "/wp-json/|rest_route=" | awk '/ {print $1, $4, $6, $7, $9}' | sort | uniq -c | sort -nr | head -n 30
`
Appliquer des correctifs directement sur un site en production relève davantage de l'inconscience que de l'audace. Créez d'abord un environnement de staging en répliquant l'intégralité de la base de données et du système de fichiers.
`bash
wp db export production_backup.sql --add-drop-table
rsync -avz --exclude='wp-content/cache' /var/www/html/ staging:/var/www/staging/
wp db import production_backup.sql
wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid
wp plugin list --update=available --fields=name,version,update_version,requires_php --format=table
`
Une fois la réplication terminée, lancez les mises à jour et prenez 5 minutes pour tester les fonctionnalités clés. Inscription, connexion, ajout au panier, appel du formulaire de paiement et soumission du formulaire de contact : il vaut mieux tout tester soi-même pour avoir l'esprit tranquille.
Il arrive de se retrouver bloqué parce que l'éditeur d'une extension ne fournit pas de mise à jour, ce qui empêche de mettre à jour le cœur immédiatement. Dans ce cas, il faut gagner du temps en bloquant l'accès à certains chemins au niveau du serveur ou du WAF. Si vous utilisez Nginx, bloquez les points de terminaison de création d'utilisateurs via l'API REST et de traitement par lots dans nginx.conf, en excluant votre propre adresse IP.
`nginx
location ~* ^/wp-json/(batch/v1|wp/v2/users) {
limit_except GET {
allow 192.0.2.1;
deny all;
}
try_files $uri args;
}
`
Au cas où, ajoutez également un script de sauvegarde automatique qui envoie la base de données et le dossier d'envois (uploads) vers Amazon S3.
`bash
#!/bin/bash
WP_PATH="/var/www/html"
BACKUP_DIR="/tmp/wp_backups"
DATE=$(date +%Y%m%d_%H%M%S)
S3_BUCKET="s3://my-wordpress-secure-backups"
mkdir -p $BACKUP_DIR
wp db export BACKUP_DIR/db_DATE.sql --path=$WP_PATH --quiet
tar -czf BACKUP_DIR/files_DATE.tar.gz -C $WP_PATH wp-content/uploads/
aws s3 cp BACKUP_DIR/db_DATE.sql S3_BUCKET/db_DATE.sql
aws s3 cp BACKUP_DIR/files_DATE.tar.gz S3_BUCKET/files_DATE.tar.gz
find $BACKUP_DIR -type f -mtime +7 -delete
`
Le travail ne s'arrête pas une fois les codes malveillants supprimés et les patchs de sécurité appliqués. L'attaquant pourrait en effet revenir en utilisant des cookies de session dérobés. Revoquez toutes les sessions et réinitialisez l'ensemble des clés de salage (salts) dans wp-config.php.
`bash
wp user list --field=ID | xargs -n 1 wp user session destroy --all
wp config shuffle-salts
`
Désactivez également la possibilité de modifier directement les fichiers d'extensions ou de thèmes depuis l'administration. C'est une protection minimale pour empêcher l'injection de code même si un attaquant parvient à obtenir des privilèges. Ajoutez les deux lignes suivantes dans wp-config.php :
`php
define( 'DISALLOW_FILE_EDIT', true );
define( 'DISALLOW_FILE_MODS', true );
`
Enfin, déposez un filtre dédié dans le dossier mu-plugins afin d'empêcher les utilisateurs non authentifiés de dérober la liste des utilisateurs via l'API REST.
`php
<?php
/**
`