
Lab Docker local pour reproduire CVE-2026-3844, un téléversement de fichier arbitraire non authentifié menant à une exécution de code à distance (RCE) dans le plugin WordPress Breeze Cache. Compare la version vulnérable 2.4.4 avec la version corrigée 2.4.5 à l'aide de services isolés et d'un PoC à impact minimal.
Laboratoire Docker local uniquement pour reproduire et comparer le comportement de CVE-2026-3844 dans le plugin WordPress Breeze Cache.
Ce dépôt démontre le comportement vulnérable de Breeze Cache 2.4.4 et le compare au comportement corrigé de Breeze Cache 2.4.5. Le laboratoire utilise deux services WordPress isolés, l’un vulnérable et l’autre corrigé, ainsi qu’un serveur de charge utile local dans le réseau Docker.
La preuve de concept est volontairement à moindre impact : elle n’utilise pas de webshell, n’expose pas de paramètre de commande, ne lance pas de shell inverse et ne nécessite pas la lecture de fichiers à l’intérieur du conteneur. La preuve repose sur un comportement HTTP observable depuis l’hôte.
CVE-2026-3844 affecte le plugin Breeze Cache pour WordPress jusqu’à la version 2.4.4 incluse. Le chemin de code vulnérable est lié à la fonctionnalité de mise en cache locale des Gravatar du plugin, plus précisément au flux fetch_gravatar_from_remote().
Lorsque l’option Breeze Host Files Locally - Gravatars est activée, les versions vulnérables peuvent récupérer un fichier distant contrôlé par l’attaquant et le stocker dans un répertoire de cache public accessible via le Web. Si le fichier récupéré est du PHP, le serveur web peut l’exécuter lorsqu’il est demandé via HTTP.
Ce laboratoire reproduit ce comportement localement :
vuln service : WordPress + Breeze Cache 2.4.4patched service : WordPress + Breeze Cache 2.4.5payload service : serveur de charge utile local réservé au réseau Dockersrcset contrôléeLe résultat attendu est :
http://127.0.0.1:8081 / Breeze 2.4.4 → la preuve PHP est mise en cache et exécutéehttp://127.0.0.1:8082 / Breeze 2.4.5 → la preuve PHP n’est pas mise en cache / lisible / exécutable.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── scripts/
│ └── seed-wordpress.sh
├── payload/
│ └── manual-proof.php
│ └── proof-cve3844.php
├── poc/
│ └── poc.py
│ └── requirements.txt
├── .gitignore
├── README.md
Host machine
│
├── http://127.0.0.1:8081 -> vuln WordPress + Breeze 2.4.4
├── http://127.0.0.1:8082 -> patched WordPress + Breeze 2.4.5
└── http://127.0.0.1:9100 -> local payload server
Docker network
│
├── vuln -> WordPress vulnerable target
├── patched -> WordPress patched target
├── vuln_db -> MariaDB for vulnerable WordPress
├── patched_db -> MariaDB for patched WordPress
└── payload -> Python static HTTP server
Les conteneurs WordPress récupèrent la charge utile via l’URL du réseau Docker :
http://payload:9100/<payload-file>.php
L’hôte vérifie le résultat via des requêtes HTTP normales vers les services WordPress.
2.4.42.4.5fetch_gravatar_from_remote()inc/class-breeze-cache-cronjobs.phpbreeze-store-gravatars-locally doit être activéeLe comportement vulnérable n’est accessible que lorsque la mise en cache locale des Gravatar est activée. Cette option est désactivée par défaut dans les installations typiques, mais ce laboratoire l’active intentionnellement pour reproduire le chemin de code vulnérable.
Dans Breeze Cache 2.4.4, le flux de localisation des Gravatar peut extraire une URL distante du HTML lié aux avatars et transmettre cette URL à fetch_gravatar_from_remote().
La version vulnérable manque de validation suffisante autour du fichier distant :
.phpLe fichier résultant est stocké sous :
/wp-content/cache/breeze-extra/gravatars/
Lorsqu’un fichier PHP y est enregistré puis demandé via Apache/PHP, le serveur l’exécute.
Dans Breeze Cache 2.4.5, le flux corrigé ajoute une validation qui empêche la charge utile de ce laboratoire d’être mise en cache en tant que PHP exécutable. Dans la reproduction locale, le même déclencheur fonctionne contre 2.4.4 mais n’expose pas le marqueur de preuve contre 2.4.5.
Ce laboratoire conserve volontairement le serveur de charge utile en local plutôt que d’utiliser un hôte de charge utile public.
download_url() de WordPress et l’API HTTP de WordPress rejettent par défaut certains noms d’hôte Docker privés et ports non standard. Les scripts d’exploitation publics utilisent souvent des URLs de charge utile HTTPS publiques, ce qui évite cette restriction. Ce laboratoire ne fait pas cela.
Pour garder la reproduction entièrement locale, le script d’initialisation installe un petit plugin d’assistance MU local uniquement qui :
payload et payload.local80 et 9100Ce plugin d’assistance ne modifie pas le code source de Breeze. Les services vulnérable et corrigé utilisent tous deux de vraies versions du plugin Breeze installées via WP-CLI.
Le plugin d’assistance n’existe que pour rendre le laboratoire Docker déterministe et strictement local.
Ce dépôt est destiné uniquement à la recherche en sécurité locale autorisée et à la démonstration dans un portfolio.
Garde-fous :
localhost et les services du réseau Dockercmd=La charge utile du PoC affiche des informations bénignes d’exécution PHP :
CVE-2026-3844_LEAST_HARM_PHP_EXEC_PROOF_<nonce>
php_sapi=apache2handler
user=www-data
uid=33
pid=<process id>
host=<container hostname>
Cela prouve le contexte d’exécution de code sans lancer de commandes shell.
requestsInstaller la dépendance Python :
python3 -m venv .venv
source .venv/bin/activate
pip install -r poc/requirements.txt
requirements.txt doit contenir :
requests
Construire et démarrer le laboratoire :
docker compose down -v --remove-orphans
docker compose up -d --build
Vérifier l’état des services :
docker compose ps
Services attendus :
vuln healthy http://127.0.0.1:8081
patched healthy http://127.0.0.1:8082
payload running http://127.0.0.1:9100
vuln_db healthy
patched_db healthy
Vérifier les journaux d’initialisation :
docker compose logs --tail=120 vuln
docker compose logs --tail=120 patched
Lignes de journal attendues :
[seed] WordPress ready at http://localhost:8081 with Breeze 2.4.4
[seed] WordPress ready at http://localhost:8082 with Breeze 2.4.5
Vérifier l’installation de WordPress :