L'injection de code (Code injection) s'impose comme l'un des risques de sécurité les plus critiques dans les systèmes basés sur l'IA, particulièrement lorsque les grands modèles de langage (LLMs) sont connectés à des bases de données, des API ou des environnements de script. Alors que les entreprises s'appuient de plus en plus sur les LLMs pour automatiser des requêtes, générer du code ou orchestrer des tâches système, la surface d'attaque s'étend, transformant les entrées de prompt en vecteurs potentiels d'exploitation.
Dans cet article, nous détaillons comment fonctionne l'injection de code dans le contexte de l'IA, comment elle diffère de l'injection de prompt, et quelles défenses vous pouvez mettre en œuvre pour protéger votre stack. Si vous explorez également les meilleures pratiques de sécurité LLM ou comparez les passerelles IA aux passerelles API traditionnelles, notre blog vous aidera à approfondir votre compréhension des vulnérabilités natives de l'IA.
Qu'est-ce que l'Injection de Code ?
L'injection de code est une forme d'exploitation de sécurité où un attaquant trompe une application pour lui faire exécuter des commandes ou des requêtes non intentionnelles. Traditionnellement, l'injection de code a été étudiée dans le contexte des applications web (par ex., injection SQL, injection de commande shell) où des entrées incorrectement assainies (sanitized) conduisent à l'exécution de code non fiable.
Dans les systèmes basés sur les LLMs, nous voyons une nouvelle variante de cette menace. Un LLM peut générer ou exécuter une requête SQL, un appel API ou un script basé sur un prompt utilisateur. Si l'entrée de l'utilisateur est malveillante, elle pourrait manipuler de tels appels système externes, entraînant l'exécution de commandes ou requêtes nuisibles, un accès non autorisé aux données, une exécution de code à distance (remote code execution), ou une élévation de privilèges (privilege escalation).
Injection de Code vs. Injection de Prompt
Bien que liées, l'« injection de prompt » implique typiquement de tromper un LLM pour qu'il retourne un texte spécifique ou ignore les contraintes imposées par le développeur. L'injection de code va plus loin : l'objectif de l'adversaire n'est pas seulement de manipuler du texte, mais d'exécuter des commandes ou requêtes malveillantes dans le contexte applicatif plus large.
Comment l'Injection de Code Affecte les LLMs et les Agents
Les LLMs et les agents IA autonomes jouent un rôle central dans les applications modernes, agissant comme intermédiaires entre les entrées utilisateur et les opérations système. Ces agents génèrent souvent du code ou du contenu dynamique qui est exécuté par d'autres sous-systèmes, ce qui en fait des cibles privilégiées pour les attaques par injection qui exploitent leur capacité à interagir avec les bases de données, les API et les commandes système. Voici des scénarios courants dans lesquels l'injection de code devient dangereuse :
- Interprétation Directe de Code par les LLMs : Certains environnements basés sur les LLMs permettent aux utilisateurs d'exécuter du code que le modèle a généré. Si un attaquant peut intégrer des scripts malveillants dans la sortie du LLM, ces scripts pourraient être exécutés sans examen approprié.
- Passage de Paramètres Malveillants aux Requêtes de Base de Données : Les développeurs s'appuient parfois sur les LLMs pour construire des requêtes SQL ou NoSQL à partir d'instructions en langage naturel. Un attaquant pourrait élaborer une entrée qui force le LLM à construire des requêtes contenant ou d'autres commandes destructrices.Copied!
1DROP TABLE
- Appels API ou Commandes Système : Les systèmes peuvent autoriser le LLM à appeler des points de terminaison (endpoints) d'API. Les attaquants peuvent en abuser en injectant des paramètres, chemins ou charges utiles (payloads) supplémentaires, entraînant un comportement indésirable. De même, lorsque les LLMs génèrent des commandes shell, l'injection de drapeaux (flags) ou d'arguments hostiles est possible.
- Injections Hors-Prompt : Ce n'est pas toujours le prompt qui véhicule les injections de code malveillantes. Les en-têtes HTTP, les paramètres de requête, les variables d'environnement ou les champs de formulaire peuvent contenir des chaînes d'injection qui façonnent finalement les actions du LLM lorsqu'il interagit avec les bases de données, les API et les commandes système. Ceci est particulièrement pertinent lorsque l'application fusionne ces valeurs dans une seule chaîne de contexte pour le LLM.
Comment Fonctionnent les Attaques par Injection de Code
Les attaquants s'appuient généralement sur deux ingrédients pour l'injection de code : un "point d'entrée" vulnérable et un système qui exécutera ou interprétera le code injecté. Dans un scénario LLM :
1. Exploitation de l'Interface en Langage Naturel du LLM L'attaquant fournit une entrée qui ressemble à du texte légitime mais qui est conçue pour produire une charge utile malveillante lorsque le LLM exécute des requêtes ou des commandes. 2. Enchaînement de Vulnérabilités Les LLMs fonctionnent rarement de manière isolée. L'injection de code devient possible lorsque la sortie du LLM est prise pour argent comptant par un autre composant comme une couche de base de données, un shell ou une API tierce. Si le système n'assainit ou ne valide pas la sortie du LLM, l'attaquant peut escalader ses privilèges ou exécuter du code arbitraire. 3. Chemins d'Exécution Non Sécurisés L'injection de code découle souvent d'une confiance excessive dans les sorties LLM. Lorsque les développeurs connectent directement les LLMs à des environnements d'exécution tels que des interpréteurs, des pipelines CI ou des clients API sans introduire de portes de révision ou de validation, ils créent par inadvertance des surfaces d'attaque.
Types d'Attaques par Injection de Code
Les attaques par injection de code se présentent sous diverses formes, chacune ciblant différents composants d'un système basé sur LLM. Ces attaques exploitent les vulnérabilités dans la manière dont les modèles génèrent, interprètent ou exécutent le code, entraînant des conséquences involontaires telles que l'accès non autorisé aux données, la manipulation du système ou l'exécution de code à distance (RCE). Ci-dessous, nous décrivons les types les plus courants d'attaques par injection de code et leur impact potentiel sur les applications LLM.
Injection SQL & Injection NoSQL
Les attaquants injectent des instructions SQL ou NoSQL malveillantes telles que 1DROP TABLE users;
1$ne: null
Injection de Commande Shell
Lorsque les sorties LLM sont interprétées comme des commandes ou des scripts shell, les attaquants peuvent intégrer des caractères spéciaux comme 1|
1&&
1;
Injection de Paramètre API
Si un LLM génère ou manipule des appels API, les attaquants peuvent élaborer des prompts qui modifient les URL des points de terminaison, modifient les méthodes HTTP ou insèrent des paramètres malveillants. Par exemple, ajouter 1?admin=true
Injection de Langage de Script
Les LLMs génèrent souvent du code dans des langages comme Python ou JavaScript pour une utilisation dans des composants en aval. Les attaquants peuvent abuser de cette capacité en intégrant une logique malveillante dans les fonctions, telles que des boucles infinies, des scripts d'exfiltration de données ou des appels 1os.system()
Injection Basée sur les En-têtes ou les Métadonnées
Le code malveillant peut également être caché dans des sources d'entrée autres que les prompts, telles que les en-têtes HTTP, les cookies, les paramètres de requête ou les champs de métadonnées. Si ces entrées sont fusionnées dans le contexte transmis au LLM, le modèle peut générer sans le savoir une sortie qui reflète ou exécute la charge utile malveillante. Ceci est particulièrement dangereux dans les systèmes multimodaux où le contexte utilisateur est construit à partir de diverses sources dynamiques.
Comment Protéger les LLMs Contre l'Injection de Code
La prévention de l'injection de code dans les systèmes alimentés par LLM nécessite une approche en couches. Aucun contrôle unique n'est suffisant : les développeurs doivent combiner l'assainissement des entrées, le durcissement des prompts, l'isolation de l'environnement et la surveillance de l'exécution. Centraliser ces protections au niveau d'une passerelle LLM (LLM gateway) est un moyen de déployer un système de défense multicouche et évolutif.
-
Détection d'Injection de Code au Niveau du Prompt : Utilisez des modèles de langage dédiés pour analyser les prompts à la recherche de signes d'instructions de code malveillantes ou hors contexte. Ces modèles de détection peuvent identifier les injections de code suspectes ou cachées dans les prompts.
-
Filtrage d'Injection au Niveau Applicatif : Déployez des systèmes de détection d'injection au niveau de l'application pour analyser les en-têtes HTTP, les paramètres de requête et les charges utiles à la recherche de schémas d'injection connus. Cela empêche l'empoisonnement du contexte en amont qui pourrait affecter l'interprétation ou la prise de décision du LLM, même si le prompt lui-même semble bénin.
-
Assainissement du Code (Code Sanitization) : Bloquez entièrement les entrées de code dans les prompts pour les cas d'utilisation qui ne nécessitent pas d'interprétation ou d'exécution de code. Si le code fourni par l'utilisateur est nécessaire, assainissez-le et échappez-le pour empêcher les composants en aval de le mésinterpréter comme exécutable. Ceci est particulièrement important dans les applications où les sorties LLM sont automatiquement transmises à des interpréteurs, des scripts ou d'autres systèmes.
-
Conception des Prompts et Isolation Contextuelle : Les instructions utilisateur doivent être isolées de la logique système pour prévenir les comportements involontaires. Fusionner l'entrée utilisateur brute avec des commandes ou des requêtes sans validation ouvre la porte à l'injection. Des alternatives plus sûres comme les requêtes paramétrées ou le templating aident à atténuer ce risque.
-
Red Teaming : Exécutez des tests adversariaux continus sur vos points de terminaison LLM et agent pour trouver les vulnérabilités d'injection avant les attaquants, et identifier où les injections de code pourraient conduire à une exécution dangereuse.
-
Surveillance et Détection d'Anomalies : Journalisez tous les prompts et interactions entre l'utilisateur et le LLM, et mettez en place un système d'alerte en temps réel qui recherche les motifs malveillants ou inhabituels, tels que des instructions de code répétées.
Conclusion
L'injection de code est un risque majeur dans les applications basées sur l'IA, en particulier lorsque les modèles LLM interagissent avec des systèmes externes tels que les bases de données SQL, les API et les interpréteurs de code. Une combinaison de mécanismes défensifs comme les passerelles LLM et de stratégies offensives telles que le red teaming, soutenue par de bonnes pratiques de développement comme l'assainissement des entrées, peut éliminer les vulnérabilités d'injection de code dans vos applications LLM.