Sites vitrines PME : scanner les CVE d'upload de plugins Joomla avec Nuclei (webshell)
Détection vulnérabilité plugin Joomla upload CVE : une vague KEV touche SP Page Builder, Joomlack, iCagenda et Balbooa Forms. Méthode Nuclei anti faux positifs.
Début juillet, plusieurs entrées rejoignent le catalogue CISA KEV pour des extensions Joomla parmi les plus déployées sur les sites vitrines de PME : SP Page Builder, Joomlack Page Builder, iCagenda et Balbooa Forms. Le défaut commun est aussi simple que redoutable : un point d'upload de fichier insuffisamment restreint, qui accepte un .php là où seule une image aurait dû passer. Résultat concret : un webshell déposé en une requête, sans authentification préalable dans plusieurs cas.
Le réflexe collectif reste tourné vers WordPress, qui concentre l'attention des chercheurs comme des attaquants. Joomla équipe pourtant une part significative des sites vitrines et institutionnels de PME françaises, souvent installés une fois par un prestataire puis laissés sans suivi pendant des années. Un CVSS critique sur un plugin d'upload, sur ce terrain-là, n'est pas une hypothèse académique : c'est une porte dérobée qui attend.
Le point aveugle des sites vitrines PME
Un site vitrine Joomla n'est presque jamais surveillé comme un actif critique. Pas d'EDR, pas de WAF actif, parfois pas même de sauvegarde récente. Le prestataire qui l'a installé a rarement de contrat de maintenance en cours. C'est exactement le profil d'actif que les campagnes de scan automatisées ciblent en masse une fois une CVE d'upload publiée : peu de bruit de détection, peu de chances qu'une compromission soit repérée avant des mois.
Pour un cabinet qui gère un parc de sites clients, la question n'est plus « est-ce que ce site a été touché » mais « lequel, parmi les vingt sites Joomla du portefeuille, ne l'a pas encore été ».
La vague de juillet : quatre plugins, un même défaut
Les avis de sécurité publiés ce mois-ci décrivent un schéma récurrent sur les quatre extensions : un composant Joomla expose un point de terminaison d'upload (souvent lié à un formulaire de contact, un constructeur de page ou un module d'événements) et valide l'extension du fichier côté client uniquement, ou via une liste noire contournable (double extension, casse, caractère nul).
Le point de départ de toute détection reste l'avis lui-même, pas un exploit public. Un proof-of-concept qui circule sur un dépôt sans licence explicite reste la propriété de son auteur ; le fait technique décrit dans l'avis (« ce chemin, ce paramètre, cette réponse ») n'appartient à personne et constitue la matière première légitime d'un template.
id: cve-2026-0001-joomla-pagebuilder-upload
# CVE illustrative : le principe compte plus que le numéro choisi.
info:
name: "Joomla Page Builder Plugin < 5.x - Unrestricted File Upload"
author: threatclaw
severity: critical
description: |
Le point de terminaison d'upload du composant expose /components/com_pagebuilder/
et accepte un fichier .php sans validation serveur de l'extension.
classification:
cve-id: CVE-2026-0001
cvss-score: 9.8
tags: cve,cve2026,joomla,upload,webshellEmpreinte Joomla et version du plugin, sans bruit
Avant toute tentative d'upload, deux vérifications passives suffisent à qualifier la cible : confirmer qu'il s'agit bien de Joomla, puis identifier la version exacte du plugin visé.
http:
- method: GET
path:
- "{{BaseURL}}/administrator/manifests/files/joomla.xml"
- "{{BaseURL}}/language/en-GB/en-GB.xml"
matchers:
- type: word
part: body
words:
- "<name>Joomla"Le marqueur de version du plugin, lui, se lit presque toujours dans le manifeste exposé sous /components/ ou dans les fichiers publics servis sous /media/ :
- method: GET
path:
- "{{BaseURL}}/administrator/components/com_pagebuilder/pagebuilder.xml"
matchers:
- type: regex
part: body
regex:
- '<version>([0-9.]+)</version>'
internal: trueCette empreinte suffit à écarter immédiatement les sites qui ne font pas tourner l'extension, sans envoyer la moindre requête à risque. C'est la première barrière anti-bruit, avant même de songer à l'upload.
Le gabarit du template Nuclei : requêtes chaînées, pas un simple GET
C'est ici que la majorité des templates rapidement écrits échouent : ils se contentent de vérifier la version du plugin par une simple requête GET et concluent « vulnérable » sur cette seule base. Un tel gabarit ignore les correctifs partiels, les configurations qui désactivent l'upload public, et génère un flot de faux positifs inexploitable pour une équipe qui gère plusieurs dizaines de sites.
La méthode correcte enchaîne deux requêtes : un POST d'upload inoffensif, puis une relecture qui confirme que le fichier déposé est bien accessible et interprété.
flow: |
http(1)
http(2)
http:
- method: POST
path:
- "{{BaseURL}}/components/com_pagebuilder/upload.php"
multipart:
- name: file
filename: "tc-check-{{randstr}}.php"
content: "<?php echo 'tc-marker-{{randstr}}'; ?>"
matchers:
- type: status
status:
- 200
- method: GET
path:
- "{{BaseURL}}/media/com_pagebuilder/uploads/tc-check-{{randstr}}.php"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
part: body
words:
- "tc-marker-{{randstr}}"Le fichier déposé n'exécute rien d'autre qu'un simple echo d'un marqueur unique généré à la volée. Il ne s'agit pas d'exploiter la faille pour en tirer un accès, mais d'obtenir le signal le plus léger et le plus fiable qu'elle existe réellement : le fichier a été accepté, stocké à un chemin prévisible, et son contenu a été exécuté par le serveur. Le matcher se déclenche sur la réponse d'upload confirmée, jamais sur la seule présence de la version vulnérable.
Vérifier qu'un webshell n'est pas déjà en place
Un parc de sites qui n'a jamais été audité peut déjà héberger une compromission antérieure à la publication de la CVE. Un second passage, distinct du test d'exploitation, recherche les traces d'un dépôt déjà réalisé : fichiers .php au nommage suspect dans les dossiers d'upload habituels, et réponses contenant des motifs caractéristiques d'un webshell (fonctions eval, contenus encodés en base64, chaînes system(, shell_exec().
http:
- method: GET
path:
- "{{BaseURL}}/media/com_pagebuilder/uploads/"
- "{{BaseURL}}/images/icagenda/uploads/"
matchers:
- type: word
part: body
words:
- ".php"
- method: GET
path:
- "{{BaseURL}}/media/com_pagebuilder/uploads/{{1}}"
matchers:
- type: word
part: body
words:
- "eval("
- "base64_decode"
- "system("
condition: orCe scan de vérification n'exploite rien : il lit ce qui est déjà exposé publiquement. Un résultat positif ici n'est pas une alerte de vulnérabilité, c'est une alerte d'incident, à traiter en priorité absolue devant toute mise à jour de plugin.
Contre les faux positifs : prouver l'upload, pas le déduire
L'erreur la plus coûteuse est de conclure à la vulnérabilité à partir de la seule présence du plugin, ou d'un numéro de version qui paraît antérieur au correctif. Deux pièges reviennent souvent : le correctif rétroporté (la version affichée reste ancienne alors qu'un correctif ciblé a été appliqué en amont) et la configuration qui désactive l'upload public par défaut sur certaines installations personnalisées.
La discipline appliquée ici tient en une phrase : ne jamais déclarer « vulnérable » sans une preuve d'upload effectif, confirmée par une relecture. Avant d'intégrer un template dans un pack diffusé, il est validé sur les deux scénarios : une installation volontairement vulnérable de la version concernée (le template doit se déclencher), et la même installation une fois patchée (le template doit rester silencieux). Un template qui échoue au second test n'est jamais publié tel quel.
Cadrer l'usage : scan périodique du parc, remédiation
Pour un cabinet qui gère un portefeuille de sites clients, la bonne cadence est un scan périodique de l'ensemble du parc, pas une vérification ponctuelle au moment de la publication de la CVE. Les nouvelles installations, les migrations de plugin et les correctifs appliqués par des tiers font évoluer la surface en continu.
nuclei -l parc-sites-clients.txt \
-t cve-2026-0001-joomla-pagebuilder-upload.yaml \
-t cve-2026-0002-joomlack-upload.yaml \
-t cve-2026-0003-icagenda-upload.yaml \
-t cve-2026-0004-balbooa-forms-upload.yaml \
-severity critical,high \
-o resultats-scan-joomla.jsonQuand un résultat positif remonte, la remédiation suit un ordre strict : mise à jour immédiate du plugin vers la version corrigée, puis recherche systématique de compromission (le scan de vérification ci-dessus) avant de considérer le site comme sain. Mettre à jour sans avoir vérifié l'absence de webshell revient à refermer une porte en laissant l'intrus à l'intérieur.
En résumé
La vague KEV de juillet sur SP Page Builder, Joomlack, iCagenda et Balbooa Forms rappelle une réalité négligée : les sites vitrines Joomla des PME portent des CVE critiques d'upload de fichier, et ne sont surveillés par personne. La méthode qui tient dans la durée part de l'avis, pas d'un exploit copié, fingerprinte la version sans bruit, chaîne une requête d'upload inoffensive et sa relecture plutôt que de conclure sur un simple numéro de version, et distingue clairement le scan de vulnérabilité du scan de compromission déjà en place.
C'est exactement cette rigueur que nous appliquons dans le pack Nuclei ThreatClaw : des templates validés sur le moteur réel, priorisés par le catalogue KEV, prêts à tourner sur l'ensemble d'un parc de sites clients dès la publication d'une CVE critique.
Articles liés
Une désérialisation de données non fiables donne une RCE sur SharePoint on-premise. Au KEV, exploitée par Storm-2603. Règle Sigma sur w3wp et détection Nuclei.
Un cookie d'override mal validé ouvre une session GlobalProtect non autorisée. Score relevé à 7.8, au KEV, exploité. Détection Nuclei et mitigation immédiate.
Un jeton OIDC non signé donne un accès technicien à SimpleHelp RMM. CVSS 10, au KEV, exploité pour livrer des voleurs. Détection Nuclei et comptes à surveiller.
CVE-2026-15409 (SSRF, CVSS 10) et CVE-2026-15410 (RCE root) frappent les SMA1000, au KEV. Versions correctives, IOC et détection Nuclei pour prioriser.