🛡️ Sécurité

Audit de sécurité rapide d'un site : checklist 30 minutes

Avant livraison client ou en audit annuel : une checklist pragmatique en 10 blocs pour détecter les vulnérabilités évidentes d'un site WordPress hébergé sous Plesk, sans y passer la journée.

intermédiaire ⏱ 20 min Mise à jour : 2026-04-24

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.

💡
Prérequis
Accès SSH à l'abonnement Plesk, WP-CLI installé (dispo par défaut sur l'infra Datacampus), et les URL publiques des sites à scanner. Gardez un éditeur ouvert pour noter les actions à reprendre.

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.com non reconnu par le client.
  • Plus de 2 ou 3 admins sur un site vitrine classique.
  • Comptes jamais connectés depuis 6 mois.
⚠️
Un admin inconnu = arrêt de l'audit
Si vous trouvez un compte administrateur que personne ne reconnaît, ne le supprimez pas tout de suite. Basculez sur la procédure Site piraté : plan de réponse : c'est probablement déjà compromis, et effacer le compte efface des preuves utiles.

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_USER n'est pas root, et DB_PASSWORD fait au moins 20 caractères.
  • WP_DEBUG est à false en prod, et WP_DEBUG_DISPLAY aussi.
  • table_prefix n'est pas wp_ 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 RewriteRule qui redirige une partie du trafic vers un domaine externe (.ru, .cn, URL raccourcie). C'est une injection SEO classique.
  • Un php_value auto_prepend_file qui charge un fichier PHP à chaque requête.
  • Des RewriteCond sur le User-Agent (Googlebot servi différemment des humains = cloaking malveillant).
  • Plusieurs .htaccess dans des dossiers où il n'a rien à faire (wp-content/uploads/2024/08/.htaccess par 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 (www et 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-Security en 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; includeSubDomains
  • Content-Security-Policy (au moins un default-src restrictif)
  • X-Frame-Options: SAMEORIGIN (contre le clickjacking)
  • X-Content-Type-Options: nosniff
  • Referrer-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 :

  1. 2FA sur tous les admins (WordPress + Plesk).
  2. Password reset forcé pour les admins et les comptes SSH/FTP : wp user update <id> --user_pass="$(openssl rand -base64 24)".
  3. Suppression des plugins et thèmes inactifs.
  4. Mise à jour du core, des plugins et des thèmes restants.
  5. fail2ban activé avec les 3 jails minimum.
  6. 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.
Rythme conseillé
Cette checklist à la livraison d'un nouveau site, puis une fois par an sur les sites en maintenance. Sur les sites à fort enjeu (e-commerce, trafic élevé), passez à une cadence trimestrielle. 30 minutes par site deux à quatre fois par an, c'est l'assurance la moins chère du marché.

Récapitulatif

  1. Versions core, PHP, plugins, thèmes à jour, inactifs supprimés.
  2. Comptes utilisateurs revus, 2FA active, logins génériques éliminés.
  3. wp-config.php en 600, clés uniques, WP_DEBUG à false.
  4. fail2ban actif avec au moins 3 jails.
  5. Aucun PHP dans uploads/, pas de modification récente suspecte.
  6. crontab propre, chaque ligne justifiée.
  7. .htaccess sans redirection externe ni auto_prepend_file.
  8. SSL Labs note A, HSTS, TLS 1.2+.
  9. securityheaders.com note B minimum.
  10. Backups externes, récents, restauration testée dans les 6 derniers mois.

Pour aller plus loin

Besoin d'aide ?

Cette documentation ne couvre pas votre cas ? Notre support humain est là.