L'audit qu'on ne fait jamais, c'est celui qui finit par coûter un week-end de restauration. Cette checklist se fait en 30 minutes montre en main, sur un site WordPress hébergé sous Plesk. Elle ne remplace pas un pentest, mais elle attrape 90 % des failles évidentes : versions obsolètes, comptes oubliés, webshells planqués, headers absents. À lancer avant chaque livraison client et une fois par an sur les sites en maintenance.
Objectif
Détecter les vulnérabilités évidentes avant qu'un attaquant ne le fasse. On ne cherche pas la perfection, on cherche les trous béants : version WordPress de 2022, compte admin avec mot de passe faible, webshell dans uploads/, certificat expiré. En 30 minutes, vous couvrez les 10 blocs ci-dessous et vous repartez avec une liste d'actions concrètes.
1. Versions : core, PHP, plugins, thèmes
La première cause de sites piratés sur l'infra reste un plugin WordPress non mis à jour. On commence par là.
cd /var/www/vhosts/exemple.fr/httpdocs
# Version de WordPress
wp core version
wp core check-update
# Version PHP utilisée par le pool
php -v
# État de tous les plugins : actif, inactif, à jour ?
wp plugin list --fields=name,status,version,update
# Idem pour les thèmes
wp theme list --fields=name,status,version,update
Ce que vous cherchez :
- WP core en retard de plus d'une version mineure : à mettre à jour immédiatement.
- PHP < 8.1 : fin de support de sécurité, à planifier avec le client.
- Plugins inactifs : à supprimer, pas juste désactiver. Un plugin désactivé reste exploitable si son code est accessible.
- Thèmes non utilisés : garder uniquement le thème actif et un thème par défaut de secours (
twentytwentyfour).
# Supprimer les plugins inactifs d'un coup
wp plugin delete $(wp plugin list --status=inactive --field=name)
# Idem pour les thèmes inactifs (hors thème actif et parent)
wp theme delete --all
2. Comptes utilisateurs
Le compte admin qui traîne depuis la livraison initiale, le editor d'un stagiaire parti il y a deux ans, le test créé pour débugger : tous sont des portes d'entrée.
# Lister tous les utilisateurs avec leur rôle et dernière connexion
wp user list --fields=ID,user_login,user_email,roles,user_registered
# Combien d'admins ?
wp user list --role=administrator --fields=user_login,user_email
Drapeaux rouges :
- Login générique :
admin,admin1,test,webmaster,root. - Email sur un domaine externe inconnu, ou sur un
@gmail.comnon reconnu par le client. - Plus de 2 ou 3 admins sur un site vitrine classique.
- Comptes jamais connectés depuis 6 mois.
Vérifiez aussi que la 2FA est bien activée pour chaque admin. Voir Activer la 2FA partout.
3. wp-config.php
cd /var/www/vhosts/exemple.fr/httpdocs
ls -l wp-config.php
grep -E "AUTH_KEY|SECURE_AUTH_KEY|DB_USER|DB_PASSWORD|table_prefix|WP_DEBUG" wp-config.php
Ce qui doit être vrai :
- Permissions 600 ou 640 sur
wp-config.php, propriétaire = user Plesk du site. - Les 8 clés (
AUTH_KEY,SECURE_AUTH_KEY,LOGGED_IN_KEY,NONCE_KEY, et les 4*_SALT) sont uniques, pas laissées àput your unique phrase here. Régénérez-les sur api.wordpress.org/secret-key. DB_USERn'est pasroot, etDB_PASSWORDfait au moins 20 caractères.WP_DEBUGest àfalseen prod, etWP_DEBUG_DISPLAYaussi.table_prefixn'est paswp_par défaut (moins critique, mais utile).
4. fail2ban et jails actives
Côté infra Datacampus, fail2ban est actif par défaut. À vérifier en SSH si vous avez les droits (sinon, demandez au support).
sudo fail2ban-client status
sudo fail2ban-client status plesk-panel
sudo fail2ban-client status ssh
sudo fail2ban-client status plesk-wordpress
Vous devez voir au moins ces trois jails actives. Regardez le Total banned : une valeur qui bouge de semaine en semaine confirme que la protection fonctionne. Zéro ban sur 6 mois sur un site exposé est suspect (service mort ou jail mal configurée).
5. Fichiers PHP suspects dans uploads
Le classique du classique : un webshell déposé dans wp-content/uploads/ via un upload non filtré. Aucun fichier PHP n'a rien à faire là.
# Tout fichier PHP dans uploads est suspect
find /var/www/vhosts/exemple.fr/httpdocs/wp-content/uploads -type f \
\( -name "*.php" -o -name "*.phtml" -o -name "*.php5" -o -name "*.phar" \) 2>/dev/null
# Fichiers modifiés dans les 7 derniers jours sous httpdocs
find /var/www/vhosts/exemple.fr/httpdocs -type f -mtime -7 \
-not -path "*/cache/*" -not -path "*/uploads/*" 2>/dev/null
# Patterns de webshells classiques
grep -rEl "eval\s*\(\s*base64_decode|assert\s*\(\s*\\\$_(POST|GET|REQUEST)|gzinflate\s*\(\s*base64" \
/var/www/vhosts/exemple.fr/httpdocs 2>/dev/null
Un seul résultat et vous basculez sur Site piraté : plan de réponse.
Bloquer l'exécution PHP dans uploads
Une ligne dans le .htaccess du dossier uploads neutralise la classe entière d'attaque :
# /wp-content/uploads/.htaccess
<FilesMatch "\.(php|phtml|php5|phar)$">
Require all denied
</FilesMatch>
6. Crons planifiés
Les attaquants aiment planquer leur persistence dans crontab : même si vous nettoyez le site, une tâche cron réinjecte la backdoor toutes les heures. Cas déjà vu sur l'infra.
# Crontab du user Plesk du site
crontab -l
# Crons WordPress (action scheduler)
wp cron event list
# Vérifier /etc/cron.d/ si vous avez les droits
ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/ 2>/dev/null
Chaque ligne doit être justifiable : sauvegarde, WP-Cron, logrotate. Une entrée qui curl | bash une URL externe, un wget vers une IP brute, un php /tmp/... : suspect, screenshot puis ticket.
7. .htaccess : redirections et includes
find /var/www/vhosts/exemple.fr/httpdocs -name ".htaccess" -exec ls -la {} \;
cat /var/www/vhosts/exemple.fr/httpdocs/.htaccess
Ce que vous cherchez :
- Une
RewriteRulequi redirige une partie du trafic vers un domaine externe (.ru,.cn, URL raccourcie). C'est une injection SEO classique. - Un
php_value auto_prepend_filequi charge un fichier PHP à chaque requête. - Des
RewriteCondsur leUser-Agent(Googlebot servi différemment des humains = cloaking malveillant). - Plusieurs
.htaccessdans des dossiers où il n'a rien à faire (wp-content/uploads/2024/08/.htaccesspar exemple).
8. SSL/TLS
Test public en 30 secondes sur SSL Labs. Objectif : note A ou A+.
Points à valider :
- Certificat valide, non expiré, bon nom de domaine (
wwwet apex couverts). - Renouvellement automatique actif côté Plesk (Let's Encrypt coché, bouton Renouveler automatiquement).
- TLS 1.2 et 1.3 uniquement. TLS 1.0 et 1.1 désactivés.
- HSTS activé (
Strict-Transport-Securityen header). - Pas de cipher weak listé dans le rapport.
9. Headers HTTP de sécurité
Test public en 30 secondes sur securityheaders.com. Objectif minimum : note B, cible : A.
Les 5 headers qui comptent :
Strict-Transport-Security: max-age=31536000; includeSubDomainsContent-Security-Policy(au moins undefault-srcrestrictif)X-Frame-Options: SAMEORIGIN(contre le clickjacking)X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-origin
Ils se posent soit dans le .htaccess, soit via Plesk > Apache & nginx Settings > Directives Apache supplémentaires. Voir la doc Hardening général pour le bloc prêt à coller.
10. Backups
Pas de backup, pas de récupération. Les questions à poser :
- Où sont stockés les backups ? Pas sur le même disque que la prod.
- Quelle fréquence ? Quotidien minimum pour un site marchand, hebdo acceptable pour une vitrine peu modifiée.
- Rétention ? Au moins 7 jours pour couvrir la détection tardive d'un défacement.
- Date du dernier test de restauration ? Un backup jamais testé n'est pas un backup.
Côté Plesk, vérifiez dans Outils & paramètres > Sauvegardes que la planification est active et que la destination est distante (FTP externe, S3, cloud storage Datacampus).
Quick wins si quelque chose tombe
Si l'un de ces 10 points sort rouge, voici l'ordre d'application prioritaire, à faire dans la foulée de l'audit :
- 2FA sur tous les admins (WordPress + Plesk).
- Password reset forcé pour les admins et les comptes SSH/FTP :
wp user update <id> --user_pass="$(openssl rand -base64 24)". - Suppression des plugins et thèmes inactifs.
- Mise à jour du core, des plugins et des thèmes restants.
- fail2ban activé avec les 3 jails minimum.
- Blocage PHP dans uploads via
.htaccess.
Outils externes utiles
- WPScan : scanner de vulnérabilités WordPress. En ligne de commande, nécessite une API key gratuite pour la base CVE.
- SSL Labs : test TLS public, rapport détaillé en 2 minutes.
- Security Headers : scan headers HTTP, note de F à A+.
- Sucuri SiteCheck : scan malware public, détecte les défacements et les injections SEO visibles depuis l'extérieur.
Quand ouvrir un ticket Datacampus
L'audit remonte toujours des points qui dépassent le périmètre agence. Ouvrez un ticket sur le ServiceDesk pour :
- Analyse des logs d'accès sur une période donnée (recherche de patterns d'attaque, corrélation d'IPs).
- Activation du WAF ModSecurity avec les règles OWASP CRS sur le vhost.
- Blocage IP permanent d'une plage qui revient en force malgré fail2ban.
- Revue fail2ban : ajout d'une jail personnalisée, ajustement des seuils.
- Doute sur une compromission : n'hésitez pas, on préfère écarter un faux positif que passer à côté d'une vraie attaque.
Récapitulatif
- Versions core, PHP, plugins, thèmes à jour, inactifs supprimés.
- Comptes utilisateurs revus, 2FA active, logins génériques éliminés.
wp-config.phpen 600, clés uniques,WP_DEBUGà false.fail2banactif avec au moins 3 jails.- Aucun PHP dans
uploads/, pas de modification récente suspecte. crontabpropre, chaque ligne justifiée..htaccesssans redirection externe niauto_prepend_file.- SSL Labs note A, HSTS, TLS 1.2+.
- securityheaders.com note B minimum.
- Backups externes, récents, restauration testée dans les 6 derniers mois.