Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2023-6553 — Exploit de preuve de concept et analyse technique pour CVE-2023-6553, une vulnérabilité d'inclusion de fichier PHP non authentifiée permettant l'exécution de code à distance dans le plugin WordPress Backup Migration <=1.3.7. | Kitploit
Outils/GitHubGitHub/dungsocool/cve-2023-6553
Analyse des VulnérabilitésAnalyse de CodeExploitationExploitation d'Applications WebTests d'IntrusionApprentissage et Éducation
GitHubdungsocool/cve-2023-6553

CVE-2023-6553

Exploit de preuve de concept et analyse technique pour CVE-2023-6553, une vulnérabilité d'inclusion de fichier PHP non authentifiée permettant l'exécution de code à distance dans le plugin WordPress Backup Migration <=1.3.7.

Voir le dépôt
20il y a 2 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2023-6553

Inclusion de fichier PHP menant à une RCE — Plugin Backup Migration

Plugin : Backup Migration (backup-backup) ≤ 1.3.7

CVSS : 9.8 (Critique)

CWE : CWE-98 — Contrôle inadéquat du nom de fichier pour l'instruction Include/Require

Authentification requise : Aucune

Impact : Exécution de code à distance


1. Qu'est-ce que cette vulnérabilité ?

Backup Migration est un plugin WordPress assez populaire (~90 000+ installations actives) qui permet aux utilisateurs de créer des sauvegardes. Pendant le processus de sauvegarde, le plugin dispose d'un fichier nommé backup-heart.php qui s'exécute en arrière-plan — il reçoit des informations de configuration via les en-têtes HTTP pour savoir quel répertoire doit être sauvegardé, où se trouve le fichier de configuration, etc.

Le problème réside dans le fait que ce fichier fait entièrement confiance aux en-têtes HTTP envoyés par le client, intègre directement la valeur de l'en-tête dans le chemin du fichier, puis utilise require_once() pour charger le fichier depuis ce chemin. Un attaquant n'a qu'à envoyer l'en-tête Content-Dir pointant vers un répertoire contenant du code PHP malveillant → le serveur l'inclut et l'exécute automatiquement.

À noter que le fichier backup-heart.php ne nécessite aucune authentification — il vérifie uniquement si la méthode de requête est POST, sans valider aucun nonce ni privilège utilisateur. N'importe qui sur Internet peut lui envoyer une requête.

⇒ C'est une vulnérabilité zero-click.

AttributValeur
ID CVECVE-2023-6553
Score CVSS9.8 (Critique)
Pluginbackup-backup (Backup Migration) ≤ 1.3.7
AuthentificationNon requise
Interaction utilisateurAucune (zero-click)
CorrigéVersion 1.3.8

2. Connaissances de base

Inclusion de fichier en PHP

PHP dispose de fonctions comme include(), require(), require_once() utilisées pour inclure d'autres fichiers PHP dans le programme en cours d'exécution. Lorsque le chemin de fichier passé à ces fonctions provient d'une entrée utilisateur sans validation, un attaquant peut forcer le serveur à inclure n'importe quel fichier de son choix :

  • LFI (Local File Inclusion) : charge un fichier existant sur le serveur — par exemple, un fichier journal « empoisonné » avec du code PHP.
  • RFI (Remote File Inclusion) : charge un fichier depuis un serveur externe — nécessite allow_url_include=On (généralement désactivé par défaut).

Cette CVE relève de la LFI — l'attaquant contrôle le chemin passé à require_once() pointant vers un fichier PHP que l'attaquant a réussi à écrire sur le serveur.

Pourquoi les en-têtes HTTP sont-ils dangereux ?

De nombreux développeurs pensent que les en-têtes HTTP sont des métadonnées « internes » connues uniquement du serveur et du client. En réalité, les attaquants contrôlent 100 % du contenu des en-têtes — ils peuvent définir n'importe quel nom et valeur d'en-tête. Faire confiance aux en-têtes revient à faire confiance aux champs de formulaire — cela doit être validé.

define() et les constantes PHP

define('NAME', $value) crée une constante utilisée dans toute l'application. Une fois définie via define(), la valeur ne peut plus être modifiée. Si $value provient d'un attaquant, chaque endroit utilisant cette constante est affecté.

3. Analyse du code source — D'où provient la vulnérabilité ?

Étape 1 : Trouver le sink

J'ai commencé par utiliser grep pour rechercher tous les require et include dans le plugin :

grep -rn "require\|include" includes/

image.png

Les résultats de recherche ont renvoyé de nombreux appels require/include. En les examinant, la plupart étaient des appels include_once dans banner/misc.php et banner/views/index.php — ils appartiennent au code de rendu de l'interface d'administration avec des chemins codés en dur, ce qui les rend non exploitables.

Cependant, 2 lignes dans backup-heart.php ont attiré mon attention :

includes/backup-heart.php:64:   define('BMI_INCLUDES', BMI_ROOT_DIR . 'includes');
includes/backup-heart.php:118:  require_once BMI_INCLUDES . '/bypasser.php';

La ligne 118 utilise require_once avec la constante BMI_INCLUDES — si cette constante était codée en dur, ce serait sécurisé. Mais en regardant la ligne 64, j'ai vu que BMI_INCLUDES est construite à partir d'une autre constante, BMI_ROOT_DIR. Nous devons donc remonter plus loin : où BMI_ROOT_DIR reçoit-elle sa valeur ?

J'ai de nouveau utilisé grep pour la tracer :

grep -n "BMI_ROOT_DIR" includes/backup-heart.php

Résultats :

image.png

Line 62: define('BMI_ROOT_DIR', $fields['content-dir']);
Line 64: define('BMI_INCLUDES', BMI_ROOT_DIR . 'includes');

La ligne 62 montre que BMI_ROOT_DIR prend sa valeur depuis $fields['content-dir']. C'est une variable, pas une valeur fixe — nous devons ouvrir le fichier et voir ce que contient $fields.

Étape 2 : Inspection du code source — D'où vient $fields ?

J'ai ouvert backup-heart.php dans VS Code à la ligne 62 :

// Line 62
define('BMI_ROOT_DIR', $fields['content-dir']);

// Line 64
define('BMI_INCLUDES', BMI_ROOT_DIR. 'includes');

image.png

On voit clairement que $fields['content-dir'] va directement dans define(). Il faut maintenant déterminer où la variable $fields est assignée :

// Lines 7-9: Only checks POST method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit;
}

// Lines 30-33: Reads ALL HTTP headers from the request
if (isFunctionEnabled('getallheaders')) {
    $fields= getallheaders();
}

// Lines 42-46: Lowercases header names
foreach ($fieldsas $key=> $value) {
    $buffer= $value;
    unset($fields[$key]);
    $fields[strtolower($key)] = $value;
}

image.png

image.png

À ce stade, la cause racine devient limpide : $fields contient tous les en-têtes HTTP récupérés via getallheaders() — entièrement contrôlés par le client. Il n'y a ni wp_verify_nonce(), ni current_user_can(), ni vérification du chemin — il vérifie simplement la méthode POST et lit directement les en-têtes.

Étape 3 : Résumé du déroulement de l'attaque

Attacker sends POST request with header Content-Dir: /path/to/attacker/
    ↓
getallheaders() reads raw headers → $fields['content-dir'] = "/path/to/attacker/"
    ↓
define('BMI_ROOT_DIR', "/path/to/attacker/")   ← no validation
    ↓
define('BMI_INCLUDES', "/path/to/attacker/includes")
    ↓
require_once "/path/to/attacker/includes/bypasser.php"   ← executes PHP
    ↓
Attacker code runs with www-data privileges → RCE

Résumé de la cause racine : en-tête HTTP → define() → require_once(), sans aucune étape de validation entre les deux.

Étape 4 : Débogage avec Xdebug

J'ai utilisé Xdebug + VS Code pour confirmer visuellement le déroulement de l'attaque. J'ai placé 2 points d'arrêt aux lignes 62 et 118 de backup-heart.php, puis j'ai envoyé la requête d'exploitation avec curl.

Point d'arrêt 1 — Ligne 62 :

Le débogueur s'est arrêté juste à define('BMI_ROOT_DIR', $fields['content-dir']). En développant la variable $fields dans le panneau Variables, on voyait un tableau de 22 éléments — contenant tous les en-têtes HTTP envoyés par le client. Concrètement :

Télécharger l’outil