Aller au contenu

CVE-2026-7141 : RCE sur le gestionnaire de KV Cache de vLLM

La CVE-2026-7141 (CVSS 9.8) identifie une vulnérabilité architecturale sévère au sein de vLLM, l’un des moteurs d’inférence LLM à haut débit et économes en mémoire les plus largement utilisés. La faille réside dans la façon dont l’algorithme PagedAttention de vLLM gère et recycle les blocs de mémoire GPU (VRAM) utilisés pour le cache Key-Value (KV).

Lorsqu’une requête de génération est brusquement annulée ou échoue, le système renvoie les blocs de cache KV alloués au pool disponible sans écraser de manière sécurisée (mise à zéro) les données résiduelles des tenseurs. En exploitant cette “utilisation d’une ressource non initialisée” (Use of Uninitialized Resource), un attaquant peut récupérer des prompts sensibles appartenant à d’autres locataires. De plus, en concevant des charges utiles adverses spécifiques qui corrompent les métadonnées de forme (shape metadata) des tenseurs au sein de ces blocs recyclés, les attaquants peuvent déclencher une écriture mémoire hors limites dans les liaisons (bindings) C++/CUDA sous-jacentes, réussissant ainsi à s’échapper de l’environnement d’exécution Python pour obtenir une exécution de code à distance (RCE) sur la machine hôte.

Pour surmonter les goulots d’étranglement de la mémoire lors de l’inférence LLM, vLLM utilise PagedAttention, qui partitionne le cache KV en blocs de taille fixe (similaires aux pages de mémoire virtuelle d’un système d’exploitation).

La vulnérabilité se situe dans le composant BlockAllocator. Pour des raisons d’optimisation des performances, lorsqu’une séquence se termine ou est interrompue, ses blocs sont libérés en les dissociant simplement du groupe de séquences actif. La mémoire GPU sous-jacente (torch.Tensor) n’est pas écrasée par des zéros.

Bien que la lecture de données obsolètes (stale data) constitue une violation massive de la confidentialité, obtenir une RCE nécessite d’exploiter le backend C++ (ex: vllm/csrc/). Si un attaquant inonde le serveur de charges utiles de tenseurs malformées et de taille précise, puis interrompt intentionnellement la connexion, il laisse des blocs “sales” (dirty) dans la VRAM. Lorsque l’attaquant initie une requête ultérieure spécialement conçue, vLLM alloue exactement ces mêmes blocs sales. En raison de l’absence de validations des limites dans le chemin d’exécution du noyau CUDA lors du traitement des clés d’attention non initialisées, l’attaquant peut écraser des régions mémoire adjacentes dans la VRAM.

Cette écriture hors limites finit par corrompre les structures d’objets de l’API C de Python résidant dans la mémoire mappée, permettant à l’attaquant de détourner le pointeur d’instruction du processus python hébergeant le serveur API vLLM.

Le processus d’exploitation nécessite un timing précis mais aucune authentification, rendant les points de terminaison de l’API vLLM exposés sur Internet hautement vulnérables.

  1. Préparation du cache (Cache Grooming) : l’attaquant envoie des centaines de requêtes d’inférence simultanées contenant une charge utile de shellcode sérialisée et hautement spécifique, encodée sous forme de jetons de texte.
  2. Interruption brutale : avant que le modèle ne termine la génération, l’attaquant coupe toutes les connexions TCP, forçant vLLM à annuler les séquences et à renvoyer les blocs corrompus au pool libre du BlockAllocator.
  3. Requête de déclenchement : l’attaquant envoie une nouvelle requête, soigneusement calculée, conçue pour allouer exactement les blocs précédemment corrompus.
  4. Corruption de métadonnées : le noyau CUDA PagedAttention traite les blocs corrompus. L’absence de mise à zéro amène le noyau à mal interpréter les données résiduelles de l’attaquant comme des métadonnées de forme de tenseur valides, déclenchant une écriture mémoire hors limites.
  5. Exécution : l’espace mémoire de l’interpréteur Python est corrompu, détournant le flux d’exécution pour lancer le shellcode de l’attaquant, aboutissant à un reverse shell sous l’identité de l’utilisateur exécutant le service vLLM.

L’investigation de la CVE-2026-7141 est particulièrement difficile car l’exploit principal se produit dans la mémoire volatile du GPU (VRAM), laissant des traces minimales sur le système de fichiers traditionnel de l’hôte.

  • Journaux du moteur vLLM : inspectez les journaux de l’application à la recherche d’un pic massif d’avertissements Sequence aborted ou Connection dropped, immédiatement suivis de CUDA_ERROR_ILLEGAL_ADDRESS ou RuntimeError: CUDA error: an illegal memory access was encountered.
  • Journaux système : recherchez des erreurs de segmentation inattendues (segfault) dans le processus python ou des journaux dmesg montrant le pilote NVIDIA (nvidia-smi) réinitialisant l’état du GPU.
  • Surveillance des processus : comme pour l’analyse de filiation des processus standard, surveillez le processus Python vllm. Si le processus de service de l’IA génère /bin/sh, curl ou wget, l’hôte a été compromis.
  • Swap VRAM : si la VRAM du GPU a été saturée pendant l’attaque, le système d’exploitation a pu déplacer des parties du cache KV vers le disque (fichiers d’échange). Les analystes peuvent utiliser bstrings pour extraire (carve) le fichier pagefile.sys ou la partition Linux swap à la recherche du shellcode en texte clair de l’attaquant ou des charges utiles d’injection de prompt.

Logique de détection : surveiller le moteur d’inférence IA (Python) générant de manière inattendue des shells interactifs ou des utilitaires réseau.

sigma_vllm_rce_shell.yaml
title: Processus enfant suspect généré par vLLM
id: 8c9d0e1f-2a3b-4c5d-6e7f-8a9b0c1d2e3f
status: experimental
description: Détecte le moteur d'inférence vLLM générant des shells suspects, indiquant une RCE réussie via la CVE-2026-7141.
logsource:
category: process_creation
product: linux
detection:
selection:
ParentImage|endswith:
- '/python'
- '/python3'
ParentCommandLine|contains: 'vllm.entrypoints'
Image|endswith:
- '/bin/sh'
- '/bin/bash'
- '/usr/bin/curl'
- '/usr/bin/wget'
condition: selection
level: critical
tags:
- attack.execution
- cve.2026-7141
  • Mise à jour : mettez à niveau vLLM vers la version 0.8.4 ou ultérieure immédiatement. Ce correctif implémente une mise à zéro sécurisée des blocs de cache KV lors de l’annulation de séquences et durcit les vérifications de limites du noyau CUDA.
  • Imposer l’isolation des locataires : ne servez pas des modèles hautement sensibles et des points de terminaison publics depuis la même instance vLLM. Implémentez une séparation physique ou par conteneur stricte pour prévenir la fuite inter-locataires (Cross-Tenant Leakage).
  • Sandboxing de conteneurs : exécutez le conteneur Docker vLLM avec un système de fichiers racine en lecture seule (--read-only), supprimez toutes les capacités (--cap-drop=ALL), et bloquez l’accès réseau sortant pour empêcher les reverse shells de se connecter à l’attaquant.

Recherche SentinelOne

Avis de sécurité GitHub vLLM

NDSS 2025 : Fuite de prompt via KV-Cache