Si vous avez déjà vu une rafale de requêtes sur admin-ajax.php ou wp-json dans vos logs, avec des paramètres qui ressemblent à du charabia, vous avez probablement observé une phase de “recherche de vulnérabilités” automatisée. Depuis 2024–2026, ce qui change, c’est la vitesse et la précision : l’IA aide autant les chercheurs en sécurité… que les attaquants.
La menace
Le scénario le plus fréquent que je vois sur des sites WordPress (6.9.4 en avril 2026) n’est pas “un hacker génial” qui cible votre blog personnel. C’est un bot qui scanne des milliers de sites, identifie une empreinte de plugin/thème, puis tente une chaîne d’exploitation connue (ou déduite) en quelques secondes. L’IA accélère surtout deux étapes : trouver des surfaces d’attaque et générer des variantes de payloads pour contourner des filtres naïfs.
Concrètement, si une vulnérabilité est présente dans un plugin (ou dans un snippet maison), l’attaquant peut souvent :
- Lire des données sensibles : emails, métadonnées, parfois contenu de tables custom, voire clés API stockées en options.
- Modifier le site : création de comptes admin, injection de liens SEO, redirections, contenu malveillant.
- Exécuter du code (RCE) dans les pires cas : installation de backdoors PHP, exfiltration, pivot vers d’autres sites du même serveur.
- Exploiter votre serveur pour du spam : envoi d’emails, hébergement de pages de phishing, proxy.
Pourquoi l’IA change la donne côté WordPress ? Parce que WordPress est un écosystème énorme, et l’attaque “économique” consiste à industrialiser :
- Lecture de code public (plugins sur wordpress.org, thèmes, GitHub) et pattern matching de failles typiques (nonce absent,
permission_callbacktrop permissif, SQL non préparé). - Génération de tests fuzzing “intelligents” : au lieu de 10 000 payloads aléatoires, 200 payloads plausibles, adaptés à votre endpoint.
- Priorisation : l’IA aide à classer les cibles (plugins populaires, versions détectées, endpoints exposés).
Pour les stats, vous trouverez des rapports publics sur la volumétrie d’attaques et l’automatisation dans les publications Wordfence et Sucuri, mais je préfère rester sur des constats vérifiables côté site : sur un site un peu visible, des scans d’API REST et d’AJAX arrivent tous les jours. Et la majorité vise des vulnérabilités connues dans des plugins, pas le cœur WordPress.
Le risque en langage simple : si votre code accepte une entrée non fiable et la traite comme “sûre” (requête SQL, inclusion de fichier, exécution de shortcode, mise à jour d’option), l’attaquant n’a plus besoin d’inventer. L’IA l’aide à repérer exactement où appuyer.
Résumé rapide
- L’IA accélère le repérage : elle détecte des motifs de code vulnérable dans des dépôts et des plugins, puis génère des tests adaptés.
- Les failles WordPress les plus exploitées restent classiques : manque de nonce/capability, injection SQL, XSS stockée, upload non contrôlé.
- Le vrai “pare-feu” côté WordPress, c’est : validation stricte,
current_user_can(), nonces,$wpdb->prepare(), et des callbacks REST corrects. - Durcissez le serveur : en-têtes, blocage de l’exécution PHP dans
uploads, désactivation de l’éditeur de fichiers, clés fortes. - Surveillez : logs, WP-CLI, comptes admin, plugins ajoutés, tâches cron suspectes.
- Compatibilité : Divi 5 / Elementor / Avada n’empêchent pas ces attaques ; ils augmentent parfois la surface via des endpoints et des modules custom.
Code vulnérable — ce qu’il ne faut PAS faire
Je prends un exemple réaliste : un mini-plugin “maison” qui expose un endpoint REST pour rechercher des commandes (ou des leads) dans une table custom. C’est typiquement le genre de code écrit vite, testé “sur mon compte admin”, puis oublié. L’IA adore ce genre d’endpoint : c’est stable, reproductible, et souvent mal protégé.
Voici une version volontairement dangereuse. Ne copiez pas ça en production.
<?php
/**
* Plugin Name: BPCAB - Recherche Commandes (DÉMO VULNÉRABLE)
*/
add_action('rest_api_init', function () {
register_rest_route('bpcab/v1', '/orders', [
'methods' => 'GET',
'callback' => 'bpcab_get_orders_vulnerable',
// DANGER : tout le monde (même non connecté) peut appeler l'endpoint
'permission_callback' => '__return_true',
]);
});
function bpcab_get_orders_vulnerable(WP_REST_Request $request) {
global $wpdb;
// DANGER : entrée utilisateur non validée
$q = $request->get_param('q');
// DANGER : injection SQL possible (concaténation directe)
$sql = "SELECT id, email, total FROM {$wpdb->prefix}bpcab_orders WHERE email LIKE '%{$q}%' ORDER BY id DESC LIMIT 50";
$rows = $wpdb->get_results($sql, ARRAY_A);
return rest_ensure_response([
'count' => count($rows),
'rows' => $rows,
]);
}
Ce qui se passe en coulisses :
- Surface exposée : l’endpoint est public (
permission_callbackretourne vrai). Un scanner peut l’appeler sans authentification. - Entrée non fiable :
qvient de l’URL. L’attaquant contrôle entièrement la chaîne. - Injection SQL : la concaténation dans
LIKE '%{$q}%'permet d’injecter des guillemets, des commentaires SQL, et de modifier la requête.
Sans donner d’outils d’exploitation, retenez ceci : un bot n’a pas besoin de “deviner” longtemps. Avec de l’IA, il peut :
- Déduire le type de base (MySQL/MariaDB), le format de la requête, et tester des variations.
- Adapter la charge utile à votre réponse (erreurs SQL, temps de réponse, structure JSON).
- Classer la gravité : si des emails sortent, il insiste ; sinon il passe au site suivant.
Un autre anti-pattern que je croise souvent : une action AJAX admin “protégée” uniquement par le fait d’être sur admin-ajax.php. Ce n’est pas une protection.
<?php
// DÉMO VULNÉRABLE : export CSV via AJAX
add_action('wp_ajax_bpcab_export', 'bpcab_export_vulnerable');
function bpcab_export_vulnerable() {
global $wpdb;
// DANGER : pas de nonce, pas de vérification de capacité
$status = $_GET['status'] ?? 'paid';
// DANGER : entrée non nettoyée + SQL non préparé
$sql = "SELECT email, total FROM {$wpdb->prefix}bpcab_orders WHERE status = '{$status}'";
$rows = $wpdb->get_results($sql, ARRAY_A);
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=export.csv');
echo "email,totaln";
foreach ($rows as $r) {
// DANGER : CSV injection possible si email commence par = + - @
echo $r['email'] . "," . $r['total'] . "n";
}
wp_die();
}
Ici, même si l’action est “wp_ajax_” (donc nécessite une session), j’ai déjà vu des sites compromis via vol de cookies, comptes abonnés détournés, ou plugins qui exposent des nonces. Et une fois l’endpoint trouvé, l’IA aide à enchaîner sur d’autres failles.
Code sécurisé — la bonne implémentation
On garde la même fonctionnalité : rechercher des commandes par email. L’objectif : réduire la surface, contrôler l’accès, valider l’entrée, préparer la requête, et limiter la fuite de données.
Version REST sécurisée (WordPress 6.9.4+, PHP 8.1+)
<?php
/**
* Plugin Name: BPCAB - Recherche Commandes (SÉCURISÉ)
*/
add_action('rest_api_init', function () {
register_rest_route('bpcab/v1', '/orders', [
'methods' => WP_REST_Server::READABLE,
'callback' => 'bpcab_get_orders_secure',
'permission_callback' => 'bpcab_orders_permission_check',
'args' => [
'q' => [
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => function ($param) {
// Validation simple : évite les entrées vides et limite la taille
return is_string($param) && $param !== '' && strlen($param) <= 80;
},
],
'limit' => [
'type' => 'integer',
'required' => false,
'default' => 20,
'sanitize_callback' => function ($value) {
$value = (int) $value;
// Plafond strict pour éviter les extractions massives
return max(1, min(50, $value));
},
],
],
]);
});
function bpcab_orders_permission_check(WP_REST_Request $request): bool {
// Réduisez la surface : réservé aux utilisateurs capables de gérer la boutique / commandes
// Adaptez la capacité selon votre contexte (WooCommerce: manage_woocommerce, etc.)
return current_user_can('manage_options');
}
function bpcab_get_orders_secure(WP_REST_Request $request): WP_REST_Response {
global $wpdb;
$q = (string) $request->get_param('q');
$limit = (int) $request->get_param('limit');
// Normalisation : on cherche un fragment d'email, pas une expression libre
$q_like = '%' . $wpdb->esc_like($q) . '%';
// Requête préparée : protège contre l'injection SQL
$sql = $wpdb->prepare(
"SELECT id, email, total
FROM {$wpdb->prefix}bpcab_orders
WHERE email LIKE %s
ORDER BY id DESC
LIMIT %d",
$q_like,
$limit
);
$rows = $wpdb->get_results($sql, ARRAY_A);
// Minimisation : ne retournez que ce qui est nécessaire
$out = array_map(function (array $r) {
return [
'id' => (int) $r['id'],
'email' => sanitize_email($r['email']),
'total' => (float) $r['total'],
];
}, $rows);
return rest_ensure_response([
'count' => count($out),
'rows' => $out,
]);
}
Pourquoi cette version tient mieux face à des scans “augmentés” à l’IA
Explication simple :
- Accès contrôlé : même si l’endpoint est découvert, il ne répond pas sans permission.
- Entrée cadrée : taille limitée, nettoyage, format attendu.
- SQL préparé : la base ne “comprend” plus l’entrée comme une partie de la requête.
- Extraction limitée :
limitplafonné, donc même un compte compromis extrait moins.
Explication technique :
permission_callbackest votre première barrière. Un__return_truesur un endpoint qui touche la base est presque toujours une erreur.$wpdb->esc_like()+$wpdb->prepare()est le duo que j’utilise systématiquement sur lesLIKE. Sansesc_like, un attaquant peut jouer avec%et_pour élargir la recherche.- L’argument
argsderegister_rest_routefait une partie du travail tôt, avant d’entrer dans votre callback, ce qui aide à standardiser le comportement.
Version AJAX sécurisée (si vous devez rester sur admin-ajax.php)
Pour certains builders (Divi 5, Avada/Fusion) ou intégrations historiques, vous resterez peut-être sur AJAX. Faites au minimum : nonce + capability + requête préparée + protection CSV.
<?php
add_action('wp_ajax_bpcab_export', 'bpcab_export_secure');
function bpcab_export_secure() {
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'Accès refusé.'], 403);
}
// Nonce : à générer côté admin (ou via wp_localize_script)
check_ajax_referer('bpcab_export_csv', 'nonce');
global $wpdb;
$status = isset($_GET['status']) ? sanitize_key((string) $_GET['status']) : 'paid';
// Liste blanche : évite les statuts arbitraires
$allowed = ['paid', 'pending', 'refunded'];
if (!in_array($status, $allowed, true)) {
wp_send_json_error(['message' => 'Statut invalide.'], 400);
}
$sql = $wpdb->prepare(
"SELECT email, total FROM {$wpdb->prefix}bpcab_orders WHERE status = %s",
$status
);
$rows = $wpdb->get_results($sql, ARRAY_A);
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=export.csv');
$fh = fopen('php://output', 'w');
if ($fh === false) {
wp_die('Impossible de générer le CSV.');
}
// En-têtes CSV
fputcsv($fh, ['email', 'total']);
foreach ($rows as $r) {
$email = sanitize_email($r['email']);
$total = (float) $r['total'];
// Protection CSV injection : neutralise les formules
// Si une valeur commence par = + - @, on préfixe par une apostrophe
$email_safe = preg_match('/^[-+=@]/', $email) ? "'" . $email : $email;
fputcsv($fh, [$email_safe, $total]);
}
fclose($fh);
wp_die();
}
Piège réel : beaucoup de devs copient le code nonce, mais oublient de l’envoyer côté JS, ou mettent le paramètre au mauvais nom (ici nonce). Résultat : ils “désactivent temporairement” check_ajax_referer et oublient de le remettre. C’est exactement le genre de régression que l’IA exploitera dès que le code est indexé ou repéré.
Compatibilité Divi 5 / Elementor / Avada : où l’IA vous “voit”
Ces builders ne créent pas la vulnérabilité, mais ils augmentent souvent :
- Le nombre d’actions AJAX et endpoints REST (widgets, modules, previews).
- Les snippets custom (functions.php, Code Snippets, mu-plugins) ajoutés vite pour un module.
- Les dépendances (addons tiers) qui peuvent avoir leur propre historique de failles.
Si vous développez un module Divi 5 ou un widget Elementor qui appelle votre endpoint, gardez l’endpoint sécurisé identique. Côté front, vous pouvez exposer un nonce via wp_create_nonce('wp_rest') (REST) ou un nonce dédié (AJAX), mais ne confondez pas nonce et permission : le nonce ne remplace pas current_user_can().
Configuration serveur
Le durcissement serveur ne corrige pas une injection SQL dans votre code. En revanche, il limite souvent l’impact : exécution de fichiers uploadés, vol de session, clickjacking, etc. Voici des réglages que j’applique régulièrement sur des WordPress 6.9.4.
.htaccess (Apache) : bloquer l’exécution PHP dans uploads
Si votre hébergement est Apache et que .htaccess est actif, ajoutez un fichier .htaccess dans wp-content/uploads/ :
# Dans wp-content/uploads/.htaccess
<FilesMatch ".(php|phtml|phar)$">
Deny from all
</FilesMatch>
Sur certains hébergements, la directive moderne est plutôt :
# Variante Apache 2.4+
<FilesMatch ".(php|phtml|phar)$">
Require all denied
</FilesMatch>
Piège réel : j’ai vu des sites où ce fichier était placé dans wp-content/ au lieu de wp-content/uploads/. Résultat : aucune protection là où il faut.
wp-config.php : réduire les dégâts
<?php
// Désactive l'éditeur de fichiers dans l'admin (évite une escalade après compromission)
define('DISALLOW_FILE_EDIT', true);
// Optionnel : bloque aussi l'installation/édition de plugins/thèmes via l'admin
// Attention : impact sur la maintenance si vous gérez tout via l'admin
define('DISALLOW_FILE_MODS', true);
// Forcer SSL sur l'admin si votre site est en HTTPS (doit l'être)
define('FORCE_SSL_ADMIN', true);
Note : DISALLOW_FILE_MODS est très efficace contre certaines post-exploitations, mais vous devrez passer par déploiement (SFTP/Git/CI) pour les mises à jour. Sur des sites gérés “à la main”, ça crée des frictions. Je le recommande surtout en environnement pro.
En-têtes HTTP de base (Apache)
À mettre dans la conf vhost ou .htaccess (si mod_headers est actif) :
<IfModule mod_headers.c>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
Pour la CSP, évitez le copier-coller aveugle : Divi/Elementor/Avada et certains plugins cassent facilement si vous bloquez trop. Commencez en mode Report-Only si vous savez le gérer côté serveur, puis durcissez progressivement.
Vérifier si votre site est vulnérable
L’objectif n’est pas de “tester comme un attaquant”, mais de vérifier des signaux concrets : endpoints exposés, permissions, erreurs SQL, comportements anormaux. Je vous donne des méthodes sûres.
1) Lister vos routes REST (WP-CLI)
Sur un site, j’exécute souvent :
wp rest route list --format=table
Cherchez :
- Des routes custom qui retournent des données sensibles.
- Des routes dont la
permission_callbackest trop permissive (dans votre code). - Des endpoints d’addons de builder que vous n’utilisez plus.
2) Vérifier les utilisateurs admin ajoutés récemment
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered --format=table
Ce que je cherche : un admin avec un email étrange, un login “support”, “wordpress”, “admin2”, et une date récente.
3) Scanner les plugins “hors dépôt” ou inconnus
wp plugin list --fields=name,status,version,update,author,plugin_uri --format=table
Piège réel : beaucoup de sites compromis ont un plugin “mu” discret. Vérifiez :
ls -la wp-content/mu-plugins
ls -la wp-content/plugins
4) Chercher des erreurs SQL et des patterns de scan dans les logs
Dans vos logs d’accès, cherchez des pics sur :
/wp-json/avec des paramètres répétitifs/wp-admin/admin-ajax.phpavec des actions inconnues?author=,?rest_route=, tentatives surxmlrpc.phpsi encore exposé
Dans vos logs d’erreur PHP / serveur, cherchez :
- Erreurs
wpdb,MySQL server version,You have an error in your SQL syntax(souvent signe de tests d’injection). - Warnings inhabituels dans des plugins rarement touchés (souvent le point d’entrée).
Tableau de diagnostic rapide
| Symptôme | Cause probable | Vérification | Solution |
|---|---|---|---|
Pic de requêtes sur /wp-json/… avec paramètres longs |
Scan automatisé d’endpoints REST | Logs d’accès + wp rest route list |
Corriger permission_callback, limiter les données, WAF |
| Erreurs SQL dans les logs | Injection SQL tentée (ou bug) | Logs d’erreur + recherche get_results( dans code custom |
$wpdb->prepare(), validation stricte, tests |
| Nouveau compte admin inconnu | Compromission via plugin vulnérable / mots de passe | wp user list + audit emails |
Rotation mots de passe, supprimer compte, analyser point d’entrée |
Fichiers PHP dans uploads |
Upload non contrôlé / backdoor | find wp-content/uploads -name "*.php" |
Supprimer, bloquer exécution PHP, scanner intégrité |
| Redirections SEO/spam uniquement pour Google | Cloaking via plugin/backdoor | Comparer rendu connecté/non connecté, UA Googlebot | Nettoyage complet + réinstallation core + audit thèmes/plugins |
Erreurs de sécurité fréquentes
| Erreur | Risque | Solution |
|---|---|---|
permission_callback REST = __return_true “pour tester” |
Exposition publique de données / actions | Vérifier capacités (current_user_can()) + limiter champs |
| Construire du SQL avec concaténation | Injection SQL | $wpdb->prepare() + esc_like() sur les LIKE |
| Nonce absent sur AJAX / admin-post | CSRF, actions admin déclenchées à votre insu | check_ajax_referer() / check_admin_referer() |
| Confondre “utilisateur connecté” et “autorisé” | Abonné peut déclencher une action admin | Contrôle de capacité adapté (pas is_user_logged_in()) |
| Copier le snippet dans le mauvais endroit (thème parent, mauvais plugin de snippets) | Site cassé, ou code non chargé donc “fix” absent | Préférer un mini-plugin ou mu-plugin, tester staging |
| Oublier un point-virgule / parenthèse dans un snippet de sécurité | Erreur fatale, écran blanc, protections non actives | Tester sur staging + activer recovery mode + logs |
| Utiliser un hook inadapté ou mauvaise priorité | Le contrôle de permission arrive trop tard | REST: permission_callback; AJAX: vérifier avant traitement |
| Tester directement en production sans sauvegarde | Indisponibilité, perte de données | Sauvegarde + staging + plan de rollback |
| Cache non vidé (plugin/CDN) après correctif | Vous croyez que c’est corrigé, mais l’ancienne version tourne | Purger cache plugin + serveur + CDN + navigateur |
| Suivre un ancien tutoriel incompatible WP 6.9 / PHP 8.1 | Régressions, failles, warnings masquant des erreurs | Vérifier docs officielles + changelogs + tests |
Checklist de durcissement
- Mettre à jour WordPress (6.9.4+), thèmes, plugins, et supprimer ceux inutilisés (désactivé ≠ supprimé).
- Auditer vos endpoints : REST routes, AJAX actions,
admin-post.php. Tout ce qui écrit en base doit exiger capability + nonce. - Rechercher le SQL concaténé dans votre code custom :
get_results("SELECT,prepare(absent,LIKE '%$var%'. - Limiter les données retournées (principe de minimisation) : pas d’emails complets si un hash suffit.
- Bloquer l’exécution PHP dans
wp-content/uploads. - Désactiver l’éditeur de fichiers (
DISALLOW_FILE_EDIT). - Activer 2FA pour les comptes admin (plugin fiable) et imposer des mots de passe forts.
- Réduire les admins : un admin par besoin réel, sinon éditeur/manager.
- Activer des sauvegardes hors serveur (offsite) + tester la restauration.
- Journaliser : accès, erreurs PHP, et événements de sécurité (au moins créations d’utilisateurs et installations de plugins).
Que faire si le site est déjà compromis ?
Quand un site WordPress est compromis, l’erreur classique est de “supprimer le fichier suspect” et de passer à autre chose. Dans mon expérience, ça tient 48h, puis ça revient, parce que le point d’entrée n’a pas été traité.
- Mettre le site en maintenance (ou au minimum bloquer l’admin) et préserver les preuves : sauvegarde complète fichiers + base avant nettoyage.
- Changer immédiatement :
- Mots de passe WP (tous les admins),
- Mots de passe FTP/SFTP/SSH,
- Mots de passe base de données,
- Clés de sécurité WordPress (salts) dans
wp-config.php.
- Identifier le point d’entrée :
- Plugin/theme récemment ajouté ou mis à jour,
- Compte admin créé,
- Endpoint custom vulnérable,
- Accès serveur compromis.
- Réinstaller le cœur WordPress proprement (mêmes version et langue) plutôt que “nettoyer fichier par fichier”. Avec WP-CLI :
# À lancer dans le répertoire WordPress
wp core verify-checksums
wp core download --force --skip-content
- Réinstaller thèmes et plugins depuis des sources officielles (wordpress.org / éditeur), puis remettre votre code custom depuis votre dépôt (pas depuis le serveur compromis).
- Inspecter wp-content :
mu-plugins,uploads(fichiers PHP, .phtml, .phar),- fichiers récemment modifiés (
find ... -mtime).
- Auditer la base :
- Utilisateurs et rôles,
- Options suspectes (siteurl/home modifiés, injections),
- Contenu injecté (posts, widgets, templates builder).
- Purger tout ce qui sert du contenu : cache plugin, cache serveur, CDN, OPcache si possible.
- Repasser en ligne seulement après : scans, vérifications manuelles, et monitoring renforcé.
Piège réel : sur des sites Elementor/Divi/Avada, les injections se cachent parfois dans des templates ou contenus sérialisés (données de builder). Si vous restaurez “un template” depuis l’admin sans l’auditer, vous réinjectez la charge.
Conseils de maintenance et compatibilité
L’IA côté recherche de vulnérabilités a un effet secondaire : le temps entre la publication d’un correctif et les scans massifs se réduit. J’ai vu des vagues démarrer en quelques heures après un CVE public sur un plugin populaire. Ça change votre routine.
Rythme de maintenance réaliste
- Hebdomadaire : mises à jour plugins/thèmes + vérification rapide des comptes admin + check logs (erreurs, pics 404/500).
- Mensuel : audit des endpoints custom, suppression des plugins inutilisés, revue des snippets.
- Trimestriel : test de restauration de sauvegarde + revue des permissions (rôles, accès API).
Performance : sécuriser sans ralentir
- Validation tôt (dans
argsREST, au début du callback) économise des requêtes DB. - Limiter les champs réduit la taille des réponses JSON, donc moins de bande passante et moins de cache à invalider.
- Éviter les regex lourdes sur des entrées non bornées : imposez une taille max avant tout traitement.
Compatibilité builders (Divi 5 / Elementor / Avada)
- Ne “patcher” pas un problème de permission en cachant un bouton dans l’UI du builder. L’endpoint reste appelable.
- Centralisez vos endpoints dans un mini-plugin (pas dans le thème enfant) : un changement de thème ne doit pas faire disparaître vos contrôles.
- Attention aux caches : après correction, purgez aussi le cache du builder (CSS/JS générés), sinon vous testez sur de vieux scripts.
Un mot sur l’IA “défensive” (utile, mais pas magique)
Vous pouvez utiliser l’IA pour :
- Repérer des patterns risqués dans votre code (ex : “concaténation SQL”, “permission_callback true”).
- Générer des tests unitaires et des cas limites (entrée vide, très longue, caractères spéciaux).
- Résumer des changelogs de plugins pour prioriser les mises à jour.
Mais ne lui déléguez pas la décision finale. Sur WordPress, une “petite” différence (capability, contexte multisite, endpoint public) change tout. Et j’ai déjà vu des suggestions IA introduire une régression de sécurité subtile, par exemple en remplaçant une capability stricte par edit_posts “pour que ça marche”.
Ressources
- Documentation REST API (WordPress Developer Resources)
- Bonnes pratiques de sécurité pour le développement de plugins
- Nonces : API et usage recommandé
- $wpdb->prepare() (référence)
- current_user_can() (référence)
- Hardening WordPress (WordPress.org)
- WordPress Core Trac (suivi des tickets et correctifs)
- Dépôt GitHub WordPress (miroir)
- PHP Manual : Security
FAQ
Est-ce que WordPress 6.9.4 est “plus sécurisé” que les versions précédentes ?
Oui, au sens où le cœur continue de corriger des failles et d’améliorer des API. Mais la majorité des compromissions que je traite viennent de plugins, thèmes, ou code custom. Votre niveau de risque dépend plus de votre surface (extensions) que de la micro-version du core.
L’IA trouve-t-elle des failles “zéro-day” dans les plugins WordPress ?
Elle peut aider à repérer des motifs suspects et à accélérer le tri, mais les zéros-days exploitables demandent souvent une compréhension fine du contexte WordPress (capabilities, nonces, flux d’upload, sérialisation). Le danger immédiat, c’est surtout l’industrialisation des failles déjà connues ou faciles.
Un WAF suffit-il à me protéger ?
Un WAF aide beaucoup contre les scans et certaines charges génériques. Il ne remplace pas la correction du code. Une injection SQL dans un endpoint authentifié, par exemple, passera souvent “sous le radar” si le trafic ressemble à un usage normal.
Dois-je désactiver XML-RPC ?
Si vous ne l’utilisez pas (Jetpack, certaines apps, intégrations), le désactiver réduit une surface historique. Si vous l’utilisez, protégez-le (limitation de débit, mots de passe forts, 2FA, monitoring). Évitez les règles “one size fits all”.
Pourquoi limiter la taille des paramètres (ex : 80 caractères) ?
Parce que beaucoup d’attaques (et de fuzzing IA) misent sur des entrées très longues pour déclencher des comportements inattendus, des backtracking regex, ou des erreurs. Une borne simple réduit le risque et améliore les perfs.
Est-ce qu’un nonce protège contre tout ?
Non. Un nonce protège surtout contre le CSRF (déclencher une action via le navigateur d’un utilisateur). Il ne remplace pas un contrôle d’autorisation. Un utilisateur connecté mais non autorisé peut parfois obtenir un nonce via une page accessible, donc current_user_can() reste obligatoire.
Je dois mettre le code dans functions.php ou dans un plugin ?
Pour du code de sécurité et des endpoints, je privilégie un mini-plugin (ou un mu-plugin). J’ai souvent vu des protections disparaître après une mise à jour de thème, un changement de thème, ou un conflit dans un thème enfant.
Comment éviter les régressions lors d’une mise à jour de plugin ?
Staging + sauvegarde + notes de version. Et surveillez les modifications autour des endpoints (REST/AJAX) et des permissions. Les régressions typiques : un paramètre renommé (nonce), un hook changé, ou une capability “assouplie”.
Divi 5 / Elementor / Avada augmentent-ils mon risque ?
Ils augmentent surtout la surface fonctionnelle (plus de code, plus d’addons, plus d’AJAX). Ce n’est pas “dangereux” par nature, mais ça exige une hygiène stricte : addons à jour, suppression des modules inutiles, et endpoints custom sécurisés.
Que dois-je surveiller en priorité dans les logs ?
Les pics sur wp-json et admin-ajax.php, les erreurs SQL, les 500 répétées, et les requêtes vers des fichiers inattendus dans uploads. Croisez toujours avec des événements WordPress : nouveaux utilisateurs, plugins ajoutés, modifications de fichiers.
Quelle est la mesure la plus rentable “tout de suite” ?
Mettre à jour et supprimer ce qui ne sert pas, puis auditer vos endpoints custom (REST/AJAX) : permissions, nonces, et requêtes DB préparées. C’est là que je trouve le plus de failles réelles sur des sites intermédiaires.