Protéger WordPress : limiter l’accès à wp-json

Dans beaucoup de sites WordPress, le point d’entrée le plus bavard ne se trouve pas dans l’interface d’administration, mais dans les endpoints ouverts par défaut. Parmi eux, wp-json attire souvent l’attention des curieux et, plus rarement, des attaquants structurés: c’est l’API REST de WordPress. Même si elle ne “donne pas tout” sans authentification, elle expose assez d’informations pour faciliter le repérage, l’énumération d’éléments, ou la préparation d’attaques plus ciblées.

Limiter l’accès à wp-json n’est pas une panacée. C’est une mesure de réduction de surface d’attaque qui, bien faite, améliore clairement la sécurité, surtout sur des sites qui n’ont pas besoin de l’API ou dont l’usage est très maîtrisé. Le bon niveau de restriction dépend de votre contexte: thèmes, plugins, applications clientes, intégrations tierces, mobilité, webhooks, compatibilité avec des éditeurs externes.

Comprendre ce que vous protégez vraiment

Wp-json est une base de routes HTTP. Quand on parle de “limiter l’accès”, on ne parle pas d’un seul fichier, mais d’un ensemble de chemins, avec des comportements différents selon la route demandée et l’état de connexion.

    Certaines routes sont publiques. Elles renvoient des informations sur le site, comme des contenus ou des éléments de configuration selon le contexte. D’autres routes exigent des droits. Elles peuvent être sensibles mais restent protégées par authentification et autorisations. Le “risque” ne vient pas seulement de la donnée brute. Il vient aussi de la facilité à cartographier ce que le site expose, quelles extensions semblent actives, quels types de contenu existent, et parfois comment l’API répond dans des cas d’erreur.

Dans une sécurisation WordPress, l’objectif est souvent d’arrêter les fuites inutiles. “Inutile” ici ne veut pas dire “sans importance”, mais “non requis par votre usage réel”. Si votre site n’utilise pas l’API REST côté front, ou si vous ne faites pas de synchronisation via des apps externes, alors une restriction partielle ou totale vers l’API peut être raisonnable.

image

J’ai déjà vu des sites où l’API restait accessible à tous, même si aucun client externe ne l’utilisait. Résultat: logs applicatifs chargés de requêtes répétitives, et un bruit constant côté sécurité. Après restriction, l’activité liée à wp-json a chuté nettement, sans impact visible sur l’affichage. Le bénéfice est souvent aussi “opérationnel”: moins de trafic inutile, moins d’expositions et des logs plus lisibles.

Identifier les dépendances avant de fermer

Le piège classique est de couper trop fort, puis de découvrir que quelque chose d’“invisible” s’appuyait sur wp-json. Les exemples les plus fréquents:

    Un plugin de cache ou d’optimisation qui rafraîchit certaines données via l’API. Un intégrateur de recherche, un module de type “chargement dynamique” ou “sync catalogue”. Un service externe (newsletter, CRM, automatisation) qui poste ou récupère des contenus. Un éditeur mobile ou une interface d’administration distante.

Avant toute modification, faites un https://gardewp.fr/securite-wordpress/ inventaire simple. Regardez dans votre parc de plugins ceux qui annoncent des fonctionnalités d’API, d’intégration, de synchronisation ou de webhooks. Ensuite, testez le site avec votre navigation habituelle, et vérifiez aussi le cas des scripts front si vous en avez.

Une méthode pragmatique consiste à définir d’abord un mode “réduction” plutôt qu’un “mur”. Par exemple, vous pouvez réserver l’accès à wp-json à certaines adresses IP (vos bureaux, votre bastion, vos serveurs d’automatisation), puis élargir si nécessaire. Cette approche évite un scénario de coupure totale où vous devez reconstruire la compatibilité à la dernière minute.

Options de limitation: du plus simple au plus maîtrisé

Selon votre serveur (Apache, Nginx, environnement managé comme Cloud, ou reverse proxy), vous pouvez appliquer des règles au niveau du webserver, au niveau de WordPress, ou combiner les deux.

Niveau serveur: bloquer, autoriser, filtrer

Le plus efficace, c’est souvent de filtrer avant que WordPress ne soit sollicité. Moins de requêtes atteignent PHP, moins vous payez le coût applicatif, et vous diminuez la surface d’attaque.

Si vous utilisez Apache, on utilise généralement des règles dans .htaccess ou une configuration du vhost. Si vous êtes sous Nginx, on configure au niveau du server. Si vous êtes derrière un CDN ou un reverse proxy, vous pouvez aussi filtrer en amont, ce qui est parfois encore plus propre.

Niveau WordPress: restreindre via des hooks

Vous pouvez aussi modifier le comportement côté WordPress, par exemple en désactivant des routes, en limitant l’accès à certaines capacités, ou en filtrant les demandes. Cette approche peut être plus fine, mais elle dépend de l’exécution de WordPress pour décider, donc elle ne réduit pas autant la charge que le filtrage serveur.

Dans la sécurisation WordPress, je privilégie d’abord le contrôle au niveau réseau, puis je complète éventuellement côté application si j’ai besoin de nuances sur certains endpoints.

Concrètement: limiter l’accès à wp-json avec Apache (.htaccess)

Si votre site est sur Apache et que l’usage de .htaccess est disponible, vous pouvez ajouter des règles pour restreindre l’accès au chemin wp-json.

Voici une approche prudente: vous autorisez uniquement votre plage d’IP (par exemple votre IP fixe) et vous bloquez le reste. En plus, vous renvoyez un code 403 pour ne pas “donner une réponse informative”. Le code 404 peut aussi être utilisé selon votre stratégie de dissimulation, mais 403 est généralement plus lisible pour l’exploitabilité interne.

Exemple de règle à adapter (remplacez l’IP et vérifiez votre chemin):

RewriteEngine On RewriteCond %REQUEST_URI ^/wp-json(/.*)?$ [NC] RewriteCond %REMOTE_ADDR !^203\.0\.113\.10$ RewriteRule ^ - [R=403,L]

Quelques points de vigilance issus de cas réels:

    Les expressions et les séparateurs comptent. Selon la structure exacte de vos URL, ajustez le motif. Si votre serveur est derrière un proxy (CDN, load balancer), %REMOTE_ADDR peut correspondre à l’IP du proxy, pas à l’IP réelle du client. Il faudra alors gérer les en-têtes proxy correctement, ce qui est un sujet à part entière. Bloquer wp-json peut casser des outils externes qui utilisent l’API REST. D’où l’intérêt de tester, ou de commencer par autoriser un ensemble d’IP.

Si vous ne connaissez pas encore vos dépendances externes, une variante consiste à bloquer seulement certaines routes, plutôt que toutes les demandes vers wp-json. Cela demande de connaître les endpoints réellement utilisés, ce qui n’est pas toujours trivial.

Nginx: une règle claire et rapide au niveau server

Sous Nginx, l’idée est la même: interdire le chemin /wp-json sans laisser WordPress traiter la demande.

Exemple simplifié:

Location ~* ^/wp-json(/.*)?$ Allow 203.0.113.10; Deny all; Return 403;

Selon votre architecture, vous devrez potentiellement adapter le “location” pour tenir compte des chemins servis depuis un sous-dossier, ou vérifier la manière dont votre site est monté dans le système de fichiers.

Et là encore, si vous êtes derrière un proxy, l’IP du client peut être masquée. Il faut alors faire attention à vos directives de trust des headers et à la manière dont Nginx calcule le REMOTE_ADDR.

Réduction de surface: limiter l’accès plutôt que tout supprimer

“Limiter l’accès” ne veut pas dire forcément “interdire tout le monde”. Sur des sites où wp-json est utile mais pas pour tous, une stratégie plus équilibrée consiste à:

    autoriser wp-json uniquement pour certaines IP autoriser l’accès pour des clients identifiés (par exemple votre automatisation) réduire les méthodes autorisées, selon les besoins

WordPress REST utilise généralement GET pour de la consultation. Si votre cas d’usage ne nécessite que la consultation (ou rien du tout), vous pouvez réfléchir à une politique. Par exemple, autoriser GET depuis certaines sources, mais bloquer POST/PUT/PATCH depuis d’autres.

Ce niveau de décision demande un minimum d’observation des logs. Dans la pratique, regarder les requêtes réelles vers wp-json (en volume et en types HTTP) vous donne une base solide pour éviter les mauvaises surprises.

Cas particuliers: captcha, brute force et “shadow endpoints”

Un point qui revient souvent en atelier, c’est la confusion entre “sécuriser wp-admin” et “sécuriser l’API”. Oui, les attaques brute force ciblent l’auth, mais elles testent aussi l’existence de fonctionnalités.

Même si wp-json ne donne pas d’accès direct à des actions sensibles sans authentification, le simple fait d’exister et de répondre peut déclencher des tentatives automatisées. Certaines équipes ajoutent alors un blocage global de wp-json et sentent que c’est “trop”. Pourtant, pour un site vitrine sans intégration, ce blocage ressemble beaucoup à un réglage de bon sens.

Pour les sites e-commerce ou sites qui utilisent une API pour des synchronisations internes, vous devrez plutôt raisonner en “règles d’accès” que “suppression”. On protège l’accès, on réduit ce qui est public, et on garde les chemins indispensables.

Si vous utilisez déjà un pare-feu applicatif (WAF) ou un module anti-bots, vous pouvez vous appuyer sur ses capacités, mais je recommande de garder la barrière au niveau serveur, car elle coupe le trafic avant que le coût applicatif ne s’accumule.

Ajuster la réponse: 403, 404 et cohérence de l’écosystème

Quand vous limitez wp-json, la question de la réponse HTTP revient vite:

    403 signifie “je comprends la route, mais je refuse”. 404 masque l’existence de la ressource. Certains configurent 410 ou autres codes, mais je reste sur les standards courants.

Le choix dépend de votre objectif. Si vous voulez réduire la cartographie opportuniste, un 404 aide. Si vous voulez faciliter la maintenance, un 403 aide vos équipes à distinguer une restriction d’un problème d’URL. En pratique, pour des environnements d’exploitation, 403 est souvent le meilleur compromis.

Attention aussi à la cohérence avec d’autres règles. Si vous avez déjà des protections pour wp-login ou wp-admin, harmonisez vos codes. Une incohérence peut rendre vos analyses de logs plus pénibles.

Vérifier l’impact: tests simples et “signaux” dans les logs

Après modification, faites une série de tests ciblés. L’idée est d’observer ce qui change réellement, pas seulement de vérifier “ça marche”.

Vous pouvez commencer par:

    tenter d’ouvrir directement /wp-json dans le navigateur, et voir la réponse tester les pages et fonctionnalités publiques qui dépendent potentiellement de l’API surveiller les logs webserver et applicatifs sur 24 à 48 heures

Si vous voyez encore des volumes élevés de requêtes vers wp-json, c’est un signal que votre règle n’attrape pas tous les chemins. Cela arrive si votre site est accessible via un sous-dossier, ou si certaines proxys réécrivent l’URL avant d’arriver chez vous.

Voici un mini repère de vérification (sans en faire une cérémonie) :

    vérifiez le code HTTP renvoyé pour une requête vers /wp-json contrôlez que vos endpoints front (recherche, chargement dynamique, formulaires) n’échouent pas dans la console du navigateur regardez si des logs d’erreurs PHP changent après la restriction vérifiez les intégrations connues pendant une période courte, par exemple une synchronisation planifiée assurez-vous que vos outils internes (IP allow-list, VPN) peuvent encore accéder si nécessaire

Je préfère toujours ce cycle: test, observation, ajustement. Une restriction “en une fois” fonctionne parfois, mais l’expérience montre que les dépendances se cachent dans des coins.

Et si vous voulez aller plus loin: filtrer certaines routes

Dans certains cas, fermer wp-json entièrement est trop dur, mais filtrer une route spécifique est plus raisonnable.

Par exemple, vous pouvez vouloir bloquer l’accès public à des routes qui exposent des détails non nécessaires. Ou vous pouvez autoriser l’API uniquement à l’édition/authentification, tout en empêchant la consultation non requise.

Sans entrer dans une liste d’endpoints au hasard, l’approche consiste à observer d’abord les URLs exactes demandées, puis à créer une politique sur ces chemins. Cette démarche demande du discernement. Je l’ai fait sur des environnements où des plugins tiers généraient des appels à des routes distinctes selon des paramètres, et la seule façon d’être sûr était de baser la décision sur ce que le site demandait réellement.

Souvent, le meilleur indicateur n’est pas un article trouvé sur internet, mais vos propres logs.

Trade-offs: sécurité, compatibilité, maintenance

Limiter wp-json améliore la sécurité perçue, mais crée aussi des coûts:

    Compatibilité: certains plugins utilisent l’API REST, parfois sans le dire clairement dans la documentation “utilisateur”. Maintenance: à chaque nouvelle intégration, vous risquez d’avoir un incident lié à la restriction. Observabilité: si vous bloquez trop, vous perdez la visibilité sur certains comportements d’intégration, et il faut alors instrumenter ailleurs.

Il faut donc arbitrer. Un site vitrine sans intégration externe peut souvent fermer wp-json au public, et c’est généralement un gain net. Un site qui vit via des intégrations, synchronisations ou un front “riche” basé sur l’API devra garder des accès contrôlés.

Dans un cas réel, j’ai choisi une restriction par IP pour un site utilisé par un seul outil d’administration externe. Résultat: aucun incident côté public, et la maintenance restait maîtrisée, parce que l’outil avait un point d’entrée unique.

image

Comment choisir une stratégie qui tient dans le temps

Il y a une différence entre “bloquer aujourd’hui” et “rester serein dans six mois”. Pour ça, je recommande une règle simple: reliez la restriction à un besoin réel, documentez-le, et gardez une sortie de secours.

Voici une manière de structurer la décision sans transformer ça en projet:

    Si vous n’utilisez pas wp-json côté front ni via des services tiers, une restriction stricte au niveau serveur est souvent la meilleure option. Si des outils externes en ont besoin, limitez par IP ou par réseau, et testez les périodes de synchronisation. Si des plugins exigent l’API dans certaines conditions, préférez des règles plus fines, ou une approche mixte serveur plus WordPress. Si votre architecture passe par un proxy, assurez-vous que votre filtrage s’appuie sur l’IP correcte (et que vous ne créez pas une faille de confiance dans les en-têtes). Si vous êtes dans un environnement géré, vérifiez les emplacements de configuration disponibles, car tous les hébergements n’autorisent pas les mêmes niveaux de contrôle.

Cette logique évite le piège du “je bloque tout, on verra”. En production, c’est rarement une bonne stratégie.

Mesures complémentaires qui renforcent l’ensemble

Limiter wp-json n’efface pas d’autres risques. Une sécurisation WordPress sérieuse, c’est aussi:

    garder WordPress, thèmes et plugins à jour limiter les tentatives de connexion (anti brute force, throttling) surveiller les comptes à privilèges et les sessions utiliser des mots de passe solides et, quand c’est possible, l’authentification à deux facteurs réduire l’exposition des fichiers sensibles

L’intérêt de combiner les mesures, c’est d’éviter une dépendance totale à une seule barrière. Si un jour une route reste accessible par erreur, le reste du dispositif peut empêcher une exploitation.

Dernière vérification avant de déployer

Avant de valider en prod, je conseille de passer par trois contrôles:

image

1) valider que vos règles correspondent à la bonne racine d’URL (parfois votre site n’est pas à la racine “/”) 2) vérifier les logs après déploiement, idéalement sur un intervalle assez court pour repérer une casse immédiate 3) tester vos intégrations connues (même une seule requête de contrôle) plutôt que de tester “au hasard”

Wp-json est un carrefour. Le sécuriser est une bonne décision, à condition de ne pas le faire à l’aveugle. En pratique, une restriction bien ciblée réduit le bruit, diminue l’exposition et rend votre posture plus solide, sans vous priver des fonctionnalités indispensables.