18 avril 2024

Renforcer la sécurité WordPress, du développement des plugins à la configuration serveur

Il y a peu, dans le cadre de recherches sur des plugins WordPress, notre pentester Vincent Fourcade a découvert une injection de code, côté client, dans un module du célèbre CMS. Celle-ci fut vérifiée et validée par les équipes de WPScan. Aujourd’hui, une CVE lui a été attribuée. L’occasion de revenir aujourd’hui sur la sécurité, au sens large, dans le CMS WordPress, que ce soit au niveau de la couche applicative, de la configuration du serveur ou du bureau. C’est parti !

Cybersécurité
Logo

Il y a peu, dans le cadre de recherches sur des plugins WordPress, notre pentester Vincent Fourcade a découvert plusieurs injections, SQL et Javascript, dans des modules du célèbre CMS (CVE-2024-1983, CVE-2024-2956, CVE-2024-3265). L’occasion de revenir aujourd’hui sur la sécurité, au sens large, dans WordPress, que ce soit au niveau de la couche applicative, de la configuration du serveur ou du bureau. C’est parti !

La partie applicative : Sécuriser ses modules

Développer ses propres modules WordPress présente plusieurs avantages. D’une part, vous obtenez un produit sur-mesure, adapté à vos besoins. D’autre part, d’un point de vue sécurité, vous avez un produit non référencé. C’est-à-dire dont le code source n’est pas accessible publiquement (en partant du principe que votre module n’est pas diffusé).

Cependant, la logique de développement de ces outils est propre à WordPress et, à l’instar de tout environnement de travail, pour obtenir une application fonctionnelle et sécurisée, il est nécessaire de respecter certaines règles de développement.

Communiquer avec sa base de données

WordPress embarque sa propre couche d’abstraction pour communiquer avec la base de données : WPDB.

L’objet embarque les méthodes courantes qu’on attend de lui, « prepare, insert, update, select, delete… » et est plutôt simple d’utilisation.

Exemple d’utilisation de WPDB

// Créer une nouvelle instance de la classe wpdb

$wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );

$wpdb->prefix = ‘wp_’;

$query = $wpdb->prepare(

« SELECT * FROM {$wpdb->prefix}posts WHERE post_title = %s »,

$title

);

$results = $wpdb->get_results( $query );

Côté sécurité, comme avec PDO, il est nécessaire de correctement utiliser les requêtes préparées pour éviter l’injection SQL.

L’affichage côté client

WordPress fournit également plusieurs fonctions afin de permettre l’affichage de données côté client sans risquer l’injection de code. En effet, en tant qu’application de gestion de contenus, les vecteurs d’injection de code Javascript sont légion. Texte, images, formulaires, données du WYSYZG…

Aussi, il convient de connaitre et d’utiliser à bon escient les fonctions suivantes :

Fonctions d’échappements propres à WordPress 

echo esc_html( $unsafe_data ); // échappe les données avant de les afficher dans des balises HTML.

echo ‘<a href= »‘ . esc_attr( $unsafe_url ) . ‘ »>Link</a>’; // échappe les attributs HTML

echo ‘<a href= »‘ . esc_url( $unsafe_url ) . ‘ »>Link</a>’; // spécifique pour les URL

echo ‘<script>var data = ‘ . esc_js( $unsafe_data ) . ‘;</script>’; // spécifique pour du code javascript

echo ‘<textarea>’ . esc_textarea( $unsafe_text ) . ‘</textarea>’; // spécifique pour les données propres au textaera

echo wp_kses( $unsafe_html, array( ‘a’ => array( ‘href’ => array() ) ) ); // prend une liste blanche de balise HTML et nettoie la chaîne.

Les bonnes pratiques de développement

Bien entendu, il convient également de suivre les bonnes pratiques de développement propre à n’importe quel projet web.

N’utiliser que des fonctions/méthodes à jour, contrôler efficacement l’accès aux ressources, désactiver l’affichage des erreurs en production, procéder à une journalisation des erreurs et évènements, utiliser des fonctions de hachage et de chiffrement adaptées pour les données sensibles réversibles et non réversibles, classifier ces mêmes données.

Enfin, un audit de code du module, si celui-ci est important et représente une pierre angulaire de votre entreprise, permet de potentiellement détecter des failles passées sous le radar lors du recettage de l’application.

Organiser les utilisateurs côté backoffice

Au-delà du développement, il est également primordial de bien configurer les droits des utilisateurs du CMS.

En effet, il arrive souvent qu’au sein d’une entreprise, les collaborateurs aient tous un même niveau de droit élevé sur le WordPress. Il devient alors possible d’installer des modules, modifier le DOM et donc d’obtenir un webshell sur le serveur – un module de téléversement de fichier ou de modification de code suffit amplement – ou d’injecter du code Javascript impactant l’ensemble des utilisateurs. L’idéal pour un compte rédacteur est de n’avoir accès qu’à la partie « articles », par exemple.

Il convient dès lors de définir correctement les rôles et leurs droits. Plusieurs options s’offrent alors à nous.

User Role Editor

L’utilisation de modules spécifiques et reconnus permettent une gestion plus fine des rôles et des droits associés.  Il est généralement recommandé par la communauté d’utiliser « User Rôle Editor ».

WP-CLI

À l’instar du développement maison de module, si l’ajout de plugins annexes n’est pas une option, il est possible, via des vecteurs plus techniques, d’affiner les rôles et réduire leurs droits.

Par exemple, WP-CLI, (WordPress Command Line Interface) permet la gestion de votre CMS en ligne de commande. Outil extrêmement puissant pour qui est habitué aux environnements CLI, il propose, entre autres, des manières ergonomiques de créer, définir ou supprimer des rôles dans WordPress.

Ci-dessous des exemples de commandes WP-CLI pour définir un rôle et y attribuer des droits :

wp role create custom_role « Custom role »

wp role add-cap custom_role custom_capabilities

wp role add-cap editor publish_posts

WP-CLI peut également servir à mettre à jour modules, thèmes et core. Ces commandes sont pratiques et facilement exécutables dans une tâche CRON, par exemple.

#!/bin/bash

wp_path= »/var/www/htmll/LeWordpress »

wp core update –path= »$wp_path » –quiet

(script bash pour mettre à jour wp)

Dans le PHP directement

Enfin, si l’on ne souhaite ni installer de module annexe, ni utiliser WP-CLI (on peut ne pas, par exemple, avoir un accès sur la machine), il est toujours possible de définir des fonctions PHP. Celles-ci seront appelées lors de l’initialisation et produiront le même résultat. Il faut tout de même avouer que cette manière de faire semble est moins pratique et moins élégante.

Fonction PHP pour ajouter un nouveau rôle :

function ajouter_role_nouveau() {

add_role(

     ‘nom_du_role’,

     __( ‘Nom du rôle’, ‘text_domain’ ),

     array(

         // Liste des capacités du rôle

         ‘read’ => true,

         ‘edit_posts’ => true,

         // Ajoutez d’autres capacités nécessaires

     )

);

}

add_action( ‘init’, ‘ajouter_role_nouveau’ );

Fonction PHP pour ajouter des capacités à un rôle :

function ajouter_capacites_role_existants() {

$role = get_role( ‘nom_du_role’ );

$role->add_cap( ‘edit_custom_post_type’ );

}

add_action( ‘init’, ‘ajouter_capacites_role_existants’ );

Le point sécurité à retenir pour la définition de rôles personnalisés est l’existence de ces deux « capabilities » unfiltered_html et unfiltered_js.

En effet, les rôles possédant ces capacités peuvent modifier le DOM à leur convenance, côté site, mais parfois aussi dans le backoffice (les développeurs de modules semblent beaucoup se reposer sur la notion des droits pour l’affichage de certaines données, côté backoffice). Aussi, il conviendra de correctement supprimer ces droits pour toute personne n’ayant pas de légitimité à procéder à du développement front.

Il est également intéressant de noter que, dans le cadre d’une injection de code Javascript/HTML, le POC devra se réaliser avec un utilisateur n’ayant pas ces « capabilities », au risque de voir sa découverte refusée.

Fonction PHP supprimant les capacités d’écrire du Javascript et de l’HTML

function supprimer_capacite_publier_javascript_html() {

// Récupérer le rôle souhaité

$role = get_role( ‘nom_du_role’ );

// Supprimer la capacité de publier des contenus potentiellement dangereux

$role->remove_cap( ‘unfiltered_html’ );

$role->remove_cap( ‘unfiltered_js’ );

}

add_action( ‘init’, ‘supprimer_capacite_publier_javascript_html’ );

Les bonnes pratiques côté serveur

Désactiver l’accès au fichier xmlrpc.php et potentiellement certains appels à l’API de WordPress sont également des actions à mener pour affiner le niveau de sécurité de votre site.

« xmlrpc.php » est un point d’accès initialement conçu pour faciliter la communication, via le langage XML, entre WordPress et des applications clientes. Cependant, l’utilisation de XML-RPC a été associée à des problèmes de sécurité, car certaines attaques ont été facilitées par cette fonctionnalité, notamment la possibilité d’attaques par force-brute.

<Files xmlrpc.php>

Order Deny,Allow

Deny from all

</Files>

(désactiver xmlrpc.php sur apache2)

L’API de WordPress quant à elle est utilisée par de nombreux modules et thèmes, il est donc difficile de la désactiver sans effets de bord. Cependant, elle peut grandement faciliter la recherche d’informations sensibles (comptes utilisateurs, rôles associés, etc.) sur votre application, notamment via le point d’accès « /wp/v2/users ». Il est possible de désactiver ce point, via l’ajout d’une fonction dans le fichier « functions.php ».

Désactiver l’accès à /wp/v2/users

add_filter( ‘rest_endpoints’, ‘desactiver_api_liste_utilisateurs’ );

function desactiver_api_liste_utilisateurs( $endpoints ) {

if ( isset( $endpoints[‘/wp/v2/users’] ) ) {

     unset( $endpoints[‘/wp/v2/users’] );

}

return $endpoints;

}

Enfin, il conviendrait aussi de filtrer l’accès à la mire d’authentification. Le schéma idéal est d’utiliser un VPN afin de se connecter au service d’administration de votre blog, ainsi il devient extrêmement difficile pour un attaquant d’en obtenir l’accès, même s’il parvenait à récupérer des accès valides (via des fuites d’informations issues de précédent hack, par exemple). Le principe basique de la cyber : multiplier les couches de sécurité.

Filtrage par IP de wp-login.php (Apache)

#.htaccess

<Files « wp-login.php »>

order deny,allow

deny from all

allow from votre_adresse_ip

</Files>

Filtrage par IP de wp-login (nginx)

#/etc/nginx/sites-available/

location = /wp-login.php {

allow votre_adresse_ip;

deny all;

}

L’hygiène de sécurité en général

Enfin, au-delà de WordPress, qu’importe le langage, l’application des règles habituelles en matière de cybersécurité sera autant de freins à un potentiel attaquant. Cela peut être l’ajout d’une authentification multifacteur, la mise en place des journaux de suivis, l’installation d’un pare-feu applicatif, la limitation des tentatives de connexion…

La maintenance est un des points clefs pour une application, que ce soit au niveau de sa disponibilité ou de sa sécurité. Les deux notions sont d’ailleurs liées, voire intriquées. En effet, une indisponibilité résulte d’un bug, d’un défaut de configuration, provoquant une erreur fatale empêchant l’application de fonctionner normalement. Une vulnérabilité n’est rien de plus qu’un bug exploité par des tiers pour obtenir de l’application un comportement qu’elle n’aurait pas dû avoir.

Faites vous accompagner

La sécurisation de WordPress nécessite une vigilance constante. Les pratiques et configurations évoquées ici constituent une première base solide pour protéger votre site contre les menaces courantes. Mais vous l’aurez compris, chaque site est unique et peut nécessiter une approche personnalisée. Si vous avez des questions sur la sécurisation de votre site WordPress ou si vous souhaitez bénéficier d’un accompagnement pour assurer la sécurité de votre CMS, notre équipe se tient à votre disposition. Nous proposons des audits de sécurité, des formations sur mesure, et un accompagnement expert pour répondre à vos besoins spécifiques. Pour en discuter, c’est par ici.

Blog

Nos actualités cybersécurité

Cybersécurité

Certification ISO 27001 : Guide complet pour sécuriser votre système d’information

Les cyberattaques coûtent de plus en plus cher aux entreprises. Les réglementations se durcissent. Les clients exigent des garanties sur la protection de leurs données. La certification ISO 27001 répond à ces trois enjeux en structurant votre sécurité informationnelle de manière rigoureuse et auditable.

19 novembre 2025

Cybersécurité

Guide complet pour l’analyse de risque cybersécurité

La cybersécurité est une priorité essentielle pour toute entreprise souhaitant protéger ses systèmes d’information et ses données sensibles. L’analyse de risque cyber est une démarche clé qui permet d’identifier, évaluer et hiérarchiser les risques liés aux actifs informationnels, tels que les données personnelles, les infrastructures critiques ou les applications métiers. Elle aide à réduire la vulnérabilité face à des menaces comme les attaques par déni de service, les tentatives d’ingénierie sociale ou les intrusions non autorisées.

6 novembre 2025

Cybersécurité

RSSI externalisé : expert cybersécurité sur demande

Le RSSI externalisé offre une solution flexible et innovante pour les entreprises qui souhaitent améliorer leur cybersécurité sans mobiliser de ressources internes permanentes. Ce expert en sécurité intervient pour piloter la mise en place de mesures de sécurité informatique, réaliser des audits, analyser les risques et garantir la conformité réglementaire tout en gérant les incidents.

6 novembre 2025

informations

Contactez-nous

Une question ou un projet en tête ? Remplissez le formulaire, nous reviendrons vers vous rapidement pour un premier échange.

*Informations obligatoires

Les informations recueillies à partir de ce formulaire sont traitées par Digitemis pour donner suite à votre demande de contact. Pour connaître et/ou exercer vos droits, référez-vous à la politique de Digitemis sur la protection des données, cliquez ici.

Index