Mika Ayenson, PhD

Intégrer la sécurité dans les flux de travail LLM : L'approche proactive d'Elastic

Explorer l'approche innovante d'Elastic pour intégrer la sécurité dans le cycle de vie des LLM afin de se prémunir contre les vulnérabilités grâce à l'assistant IA d'Elastic.

Intégrer la sécurité aux workflow LLM : l'approche proactive d'Elastic

Nous avons récemment conclu l'un de nos événements trimestriels Elastic OnWeek, qui offre une semaine unique pour explorer des opportunités en dehors de notre quotidien habituel. En accord avec les récentes publications de l'OWASP et de l'AISC de la NSA, nous avons décidé de passer un peu de temps avec les dix principales vulnérabilités de l'OWASP pour les LLMs nativement dans Elastic. Dans cet article, nous abordons quelques opportunités de détecter des activités LLM malveillantes avec ES|QL, à savoir :

  • LLM01 : Injection rapide
  • LLM02 : Traitement non sécurisé des sorties
  • LLM04 : Modèle de déni de service
  • LLM06 : Divulgation d'informations sensibles

Elastic offre la possibilité d'auditer les applications LLM à la recherche de comportements malveillants ; nous allons vous montrer une approche en seulement quatre étapes :

  1. Interception et analyse des demandes et des réponses du MLD
  2. Enrichir les données avec des résultats d'analyse spécifiques au programme LLM
  3. Envoi de données à Elastic Security
  4. Rédiger des règles de détection ES|QL qui peuvent ensuite être utilisées pour réagir

Cette approche reflète nos efforts continus pour explorer et mettre en œuvre des stratégies de détection avancées, y compris le développement de règles de détection spécialement conçues pour les LLM, tout en restant en phase avec les technologies d'IA générative émergentes et les défis en matière de sécurité. Sur cette base, l'année dernière a été marquée par une amélioration significative de notre boîte à outils et de notre capacité globale à poursuivre sur cette voie proactive.

Elastic a lancé l 'assistant AI pour la sécurité, présentant comment l'assistant AI génératif ouvert est alimenté par la Search AI Platform - une collection d'outils pertinents pour le développement d'applications de recherche avancées. S'appuyant sur l'apprentissage machine (ML) et l'intelligence artificielle (IA), cet assistant IA fournit de puissants flux de travail prédéfinis tels que la synthèse des alertes, les suggestions de flux de travail, les conversions de requêtes et les conseils d'intégration d'agents. Je vous recommande vivement d'en savoir plus sur l'assistant IA d' Elastic et sur la façon dont les capacités s'étendent de manière transparente à l'observabilité et à la sécurité.

Nous pouvons utiliser les capacités de l'assistant d'IA en tant qu'application LLM tierce pour capturer, auditer et analyser les demandes et les réponses à des fins de commodité et pour mener des expériences. Une fois que les données sont dans un index, l'écriture de détections comportementales sur ces données devient une activité normale - nous pouvons également tirer parti de l'ensemble du moteur de détection de sécurité. Même si nous mandatons l'activité LLM de l'assistant Elastic AI dans cette expérience, elle est simplement utilisée comme véhicule pour démontrer l'audit des applications basées sur LLM. En outre, cette approche par proxy est destinée aux applications tierces qui envoient des données à Elastic Security.

Nous pouvons introduire des mécanismes de sécurité dans le cycle de vie de l'application en interceptant l'activité LLM ou en exploitant les métriques LLM observables. La pratique courante consiste à répondre aux menaces basées sur la rapidité en mettant en œuvre diverses tactiques de sécurité :

  1. Nettoyer les entrées: Assainissez et validez les entrées des utilisateurs avant de les introduire dans le modèle.
  2. Modération du contenu: Utilisez les outils de l'OpenAI pour filtrer les messages et les sorties nuisibles.
  3. Limites et surveillance des tarifs: Suivez les habitudes d'utilisation pour détecter toute activité suspecte
  4. Autoriser/Listes de blocage: Définissez les entrées acceptables ou interdites pour des applications spécifiques
  5. Ingénierie des messages-guides: Concevoir des messages-guides préconstruits qui guident le modèle vers les résultats escomptés.
  6. Gestion des rôles des utilisateurs: Contrôlez l'accès des utilisateurs pour éviter les actions non autorisées
  7. Éduquer les utilisateurs finaux: Promouvoir une utilisation responsable du modèle afin d'atténuer les risques.
  8. Red Teaming & Surveillance: Testez les vulnérabilités et surveillez en permanence les résultats inattendus.
  9. Retour d'information HITL pour la formation au modèle: Apprenez des problèmes signalés par l'homme dans la boucle afin d'affiner le modèle au fil du temps.
  10. Restreindre l'accès à l'API: Limitez l'accès au modèle en fonction des besoins spécifiques et de la vérification de l'utilisateur.

Deux fonctions puissantes fournies par OpenAI, et par de nombreux autres utilisateurs de LLM, sont la possibilité de soumettre les identifiants des utilisateurs finaux et de vérifier le contenu par rapport à une API de modération, fonctions qui placent la barre très haut en matière de sécurité des LLM. L'envoi d'identifiants hachés en même temps que la demande originale facilite la détection des abus et fournit un retour d'information ciblé, permettant une identification unique de l'utilisateur sans envoi d'informations personnelles. Par ailleurs, le point final de modération d'OpenAI aide les développeurs à identifier les contenus potentiellement dangereux tels que les discours haineux, les encouragements à l'automutilation ou la violence, ce qui leur permet de filtrer ces contenus. Il va même plus loin en détectant les menaces et les intentions d'automutilation.

Malgré toutes les recommandations et les meilleures pratiques pour se protéger contre les messages malveillants, nous reconnaissons qu'il n'existe pas de solution parfaite. Lorsque vous utilisez des capacités telles que l'API d'OpenAI, certaines de ces menaces peuvent être détectées par le filtre de contenu, qui réagira en envoyant une notification de violation de la politique d'utilisation :

Ce filtrage de contenu est utile pour résoudre de nombreux problèmes, mais il ne permet pas d'identifier d'autres menaces dans le contexte plus large de l'environnement, de l'écosystème d'applications ou d'autres alertes susceptibles d'apparaître. Plus nous pourrons intégrer des cas d'utilisation de l'IA générative dans nos capacités de protection existantes, plus nous aurons de contrôle et de possibilités pour faire face aux menaces potentielles. En outre, même si des garanties LLM sont en place pour arrêter les attaques rudimentaires, nous pouvons toujours utiliser le moteur de détection pour alerter et prendre des mesures correctives futures au lieu de bloquer silencieusement ou d'autoriser les abus.

Requêtes de proxy LLM et configuration

La solution de sécurité optimale intègre des garanties supplémentaires directement dans l'écosystème de l'application LLM. Cela permet d'enrichir les alertes avec le contexte complet des demandes et des réponses. Lorsque les requêtes sont envoyées au LLM, nous pouvons les intercepter et les analyser pour détecter d'éventuelles activités malveillantes. Si nécessaire, une action de réponse peut être déclenchée pour différer les appels HTTP ultérieurs. De même, l'inspection de la réponse du LLM peut révéler d'autres signes de comportement malveillant.

L'utilisation d'un proxy pour gérer ces interactions présente plusieurs avantages :

  • Facilité d'intégration et de gestion: En gérant le nouveau code de sécurité dans une application proxy dédiée, vous évitez d'intégrer une logique de sécurité complexe directement dans l'application principale. Cette approche minimise les changements à apporter à la structure de l'application existante, ce qui facilite la maintenance et permet de séparer plus clairement la sécurité de la logique d'entreprise. L'application principale doit seulement être reconfigurée pour acheminer ses requêtes LLM via le proxy.
  • Performance et évolutivité: Le fait de placer le proxy sur un serveur séparé permet d'isoler les mécanismes de sécurité et de répartir la charge de calcul. Cela peut s'avérer crucial lors de l'extension des opérations ou de la gestion de tâches à forte intensité de performances, en veillant à ce que les performances de l'application principale ne soient pas affectées par le traitement supplémentaire de la sécurité.

Option de démarrage rapide : Proxy avec Flask

Vous pouvez utiliser un proxy pour les connexions LLM entrantes et sortantes afin d'accélérer l'installation initiale. Cette approche peut être généralisée pour d'autres applications LLM en créant une simple application Flask basée sur Python. Cette application intercepte la communication, l'analyse pour détecter les risques de sécurité et enregistre les informations pertinentes avant de transmettre la réponse.

Il existe plusieurs SDK pour se connecter à Elasticsearch et traiter les requêtes OpenAI LLM. La version fournie de llm-detection-proxy présente les clients Elastic et OpenAI disponibles. Cet extrait met en évidence l'essentiel du proxy expérimental dans une seule route Flask.

@app.route("/proxy/openai", methods=["POST"])
def azure_openai_proxy():
   """Proxy endpoint for Azure OpenAI requests."""
   data = request.get_json()
   messages = data.get("messages", [])
   response_content = ""
   error_response = None

   try:
       # Forward the request to Azure OpenAI
       response = client.chat.completions.create(model=deployment_name, messages=messages)
       response_content = response.choices[0].message.content  # Assuming one choice for simplicity
       choices = response.choices[0].model_dump()
   except openai.BadRequestError as e:
       # If BadRequestError is raised, capture the error details
       error_response = e.response.json().get("error", {}).get("innererror", {})
       response_content = e.response.json().get("error", {}).get("message")

       # Structure the response with the error details
       choices = {**error_response.get("content_filter_result", {}),
                  "error": response_content, "message": {"content": response_content}}

   # Perform additional analysis and create the Elastic document
   additional_analysis = analyze_and_enrich_request(prompt=messages[-1],
                                                    response_text=response_content,
                                                    error_response=error_response)
   log_data = {"request": {"messages": messages[-1]},
               "response": {"choices": response_content},
               **additional_analysis}

   # Log the last message and response
   log_to_elasticsearch(log_data)

   # Calculate token usage
   prompt_tokens = sum(len(message["content"]) for message in messages)
   completion_tokens = len(response_content)
   total_tokens = prompt_tokens + completion_tokens

   # Structure and return the response
   return jsonify({
       "choices": [choices],
       "usage": {
           "prompt_tokens": prompt_tokens,
           "completion_tokens": completion_tokens,
           "total_tokens": total_tokens,
       }
   })

Avec le serveur Flask, vous pouvez configurer le connecteur OpenAI Kibana pour utiliser votre proxy.

Comme ce proxy vers votre LLM est exécuté localement, les informations d'identification et de connexion sont gérées en dehors d'Elastic, et une chaîne vide peut être fournie dans la section clé API. Avant d'aller plus loin, il est généralement conseillé de tester votre connexion. Il est important de prendre en compte d'autres implications en matière de sécurité si vous envisagez de mettre en œuvre une solution proxy dans un environnement réel - ce que ce prototype n'a pas pris en compte par souci de concision.

Nous pouvons maintenant indexer nos demandes et réponses LLM et commencer à écrire des détections sur les données disponibles dans l'index azure-openai-logs créé dans cette expérience. Nous pourrions éventuellement prétraiter les données à l'aide d'un pipeline d'ingestion Elastic, mais dans cet exemple artificiel, nous pouvons effectivement écrire des détections grâce à la puissance d'ES|QL.

Exemple de données de requête/réponse AzureOpenAI LLM

Procuration de Langsmith

Note : Le projet Langsmith Proxy fournit un proxy dockerisé pour vos API LLM. Bien qu'elle offre une solution minimisée, elle ne dispose pas, à ce jour, de capacités natives permettant d'incorporer des outils d'analyse de sécurité personnalisés ou d'intégrer directement Elastic Security.

Le proxy LangSmith est conçu pour simplifier l'interaction avec l'API LLM. Il s'agit d'une application secondaire nécessitant une configuration minimale (par exemple, l'URL de l'API LLM). Il améliore les performances (mise en cache, diffusion en continu) pour les scénarios à fort trafic. Il utilise NGINX pour plus d'efficacité et supporte le traçage optionnel pour un suivi détaillé des interactions LLM. Actuellement, il fonctionne avec OpenAI et AzureOpenAI, et un support futur est prévu pour d'autres LLM.

Attaques potentielles du LLM et possibilités de règles de détection

Il est important de comprendre que même si des listes documentées de protections n'accompagnent pas certains MLD, le simple fait d'essayer certaines de ces invites peut être immédiatement refusé ou entraîner un bannissement sur la plateforme utilisée pour soumettre l'invite. Nous vous recommandons d'expérimenter avec prudence et de comprendre l'accord de niveau de service avant d'envoyer des messages malveillants. Puisque cette exploration utilise les ressources d'OpenAI, nous vous recommandons de suivre les conseils de bugcrowd et de vous inscrire pour un compte de test supplémentaire en utilisant votre adresse e-mail @bugcrowdninja.com.

Voici une liste de plusieurs exemples plausibles pour illustrer les possibilités de détection. Chaque thème LLM comprend la description de l'OWASP, un exemple d'invite, un exemple de document, la possibilité de détection et les actions potentielles que les utilisateurs peuvent entreprendre s'ils intègrent des mécanismes de sécurité supplémentaires dans leur flux de travail.

Bien que cette liste ne soit pas exhaustive, Elastic Security Labs entreprend actuellement un certain nombre d'initiatives pour assurer le développement futur et la formalisation des règles.

LLM01 - injection rapide

Description de l'OWASP: La manipulation des LLM par le biais d'intrants artisanaux peut conduire à un accès non autorisé, à des violations de données et à une prise de décision compromise. Référence ici.

Exemple: Un adversaire peut essayer de créer des invites qui incitent le LLM à exécuter des actions involontaires ou à révéler des informations sensibles. Remarque : des outils tels que promptmap sont disponibles pour générer des idées créatives d'injection de messages et automatiser le processus de test.

Prompt:

Exemple de réponse:

Opportunité de la règle de détection: Dans cet exemple, le LLM a réagi en refusant de gérer les chaînes de connexion à la base de données en raison des risques de sécurité. Il met l'accent sur la confidentialité des informations d'identification et suggère d'utiliser des méthodes sécurisées telles que les variables d'environnement ou les coffres-forts pour les protéger.

Une requête d'appariement d'indicateurs très fragile mais basique peut ressembler à ceci :

FROM azure-openai-logs |
   WHERE request.messages.content LIKE "*generate*connection*string*"
   OR request.messages.content LIKE "*credentials*password*username*"
   OR response.choices LIKE "*I'm sorry, but I can't assist*"

Une requête un peu plus poussée permet de détecter plus de deux tentatives similaires au cours de la journée écoulée.

FROM azure-openai-logs
| WHERE @timestamp > NOW() -  1 DAY
| WHERE request.messages.content LIKE "*credentials*password*username*"
   OR response.choices LIKE "*I'm*sorry,*but*I*can't*assist*"
   OR response.choices LIKE "*I*can’t*process*actual*sensitive*"
| stats total_attempts = count(*) by connectorId
| WHERE total_attempts >= 2

Notez qu'il existe de nombreuses approches pour détecter les invites malveillantes et protéger les réponses LLM. Se fier uniquement à ces indicateurs n'est pas la meilleure approche ; cependant, nous pouvons progressivement améliorer la détection grâce à un enrichissement supplémentaire ou à de nombreuses tentatives de réponse. En outre, si nous introduisons un identifiant dans nos documents, nous pouvons encore améliorer notre requête en regroupant les tentatives basées sur le champ qui correspond à un utilisateur spécifique.

Exemple 2: l'effet Crescendo est une attaque réaliste d'évasion de prison dans laquelle un adversaire manipule progressivement un modèle linguistique par le biais d'une série de demandes apparemment innocentes qui évoluent vers une demande au modèle de décrire des scénarios hypothétiques impliquant l'accès non autorisé et la manipulation de systèmes sécurisés. Ce faisant, ils cherchent à extraire des méthodes qui pourraient potentiellement contourner les contraintes de sécurité du LLM.

Prompt:

Exemple de réponse:

Grâce à l'analyse supplémentaire du filtrage d'OpenAI, nous pouvons immédiatement détecter la première occurrence d'abus.

Opportunité de règle de détection:

FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
 AND (
     request.messages.content LIKE "*credentials*password*username*"
     OR response.choices LIKE "*I'm sorry, but I can't assist*"
     OR analysis.openai.code == "ResponsibleAIPolicyViolation"
     OR malicious
 )
| STATS total_attempts = COUNT(*) BY connectorId
| WHERE total_attempts > 1
| SORT total_attempts DESC

Cependant, lorsque vous continuez à utiliser l'effet Crescendo, nous remarquons que le pivot de conversation se débloque après le filtre de contenu initial d'OpenAI. Il est important de comprendre que même si de telles tactiques sont difficiles à prévenir, nous avons toujours la possibilité de les détecter.

Des outils d'analyse supplémentaires, comme LLM-Guard, détectent si la conversation est sensible, ce qui, dans ce cas, est inexact. Cependant, il laisse entrevoir des possibilités de suivre les comportements malveillants sur plusieurs invites. Remarque : nous pourrions également utiliser les séquences EQL comme alternative à cette requête ES|QL pour faciliter le suivi des comportements sur plusieurs événements.

FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
 AND (
     request.messages.content LIKE "*Molotov*"
     OR analysis.openai.code == "ResponsibleAIPolicyViolation"
     OR malicious
 )
| STATS attempts = count(*), max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive) BY connectorId
| WHERE attempts >= 1 AND max_sensitivity > 0.5
| SORT attempts DESC

Cette requête détecte les comportements suspects liés aux cocktails Molotov dans plusieurs événements en analysant les séquences d'entrées de journal associées à un seul utilisateur/session (identifié par connectorId). Le noyau d'interrogation filtre les événements en fonction de :

  • Correspondance de contenu: recherche des mentions de "Molotov" dans le contenu de la conversation (request.messages.content LIKE "*Molotov*")
  • **Policy Violations : Il identifie les tentatives bloquées par les filtres de sécurité d'OpenAI (analysis.openai.code == "ResponsibleAIPolicyViolation"), indiquant le début d'un comportement potentiellement suspect.
  • Prise en compte des drapeaux malveillants: Il comprend les journaux dans lesquels le système a signalé le contenu comme étant malveillant (malicious == true), ce qui permet de saisir des mentions potentiellement subtiles ou variées.
  • Analyse au niveau de la session: En regroupant les événements par connectorId, il analyse la séquence complète des tentatives au cours d'une session. Il calcule ensuite le nombre total de tentatives (attempts = count(*)) et le score de sensibilité le plus élevé (max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive)) pour l'ensemble des tentatives de cette session.
  • Signaler les sessions à haut risque: Il filtre les sessions ayant fait l'objet d'au moins une tentative (attempts >= 1) et dont le score de sensibilité maximal est supérieur à 0,5 (max_sensitivity > 0.5). Ce seuil permet de se concentrer sur les sessions au cours desquelles les utilisateurs discutent ou révèlent de manière persistante des contenus potentiellement dangereux.

En analysant ces facteurs sur plusieurs événements au cours d'une session, nous pouvons commencer à élaborer une approche permettant de détecter un schéma d'escalade des discussions, même si les événements individuels ne peuvent pas être repérés seuls.

LLM02 - Traitement non sécurisé des sorties

Description de l'OWASP: Négliger de valider les sorties LLM peut conduire à des exploits de sécurité en aval, y compris l'exécution de code qui compromet les systèmes et expose les données. Référence ici.

Exemple: Un adversaire peut tenter d'exploiter le mécanisme d'apprentissage tout au long de la vie pour générer des résultats pouvant être utilisés pour des attaques de type cross-site scripting (XSS) ou d'autres attaques par injection.

Prompt:

Exemple de réponse:

Opportunité de règle de détection:

FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE (
   response.choices LIKE "*<script>*"
   OR response.choices LIKE "*document.cookie*"
   OR response.choices LIKE "*<img src=x onerror=*"
   OR response.choices LIKE "*<svg/onload=*"
   OR response.choices LIKE "*javascript:alert*"
   OR response.choices LIKE "*<iframe src=# onmouseover=*"
   OR response.choices LIKE "*<img ''><script>*"
   OR response.choices LIKE "*<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>*"
   OR response.choices LIKE "*<IMG SRC=# onmouseover=alert('xxs')>*"
   OR response.choices LIKE "*<IMG onmouseover=alert('xxs')>*"
   OR response.choices LIKE "*<IMG SRC=/ onerror=alert(String.fromCharCode(88,83,83))>*"
   OR response.choices LIKE "*&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>*"
   OR response.choices LIKE "*<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>*"
   OR response.choices LIKE "*<IMG SRC=\"jav&#x0A;ascript:alert('XSS');\">*"
)
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
| WHERE total_attempts >= 2

Cette pseudo-requête détecte un traitement de sortie potentiellement non sécurisé en identifiant les réponses LLM contenant des éléments de script ou des tentatives d'accès aux cookies, qui sont courants dans les attaques de type Cross-Site Scripting (XSS). Il s'agit d'un shell qui pourrait être étendu par des listes d'autorisation ou de blocage pour des mots-clés bien connus.

LLM04 - modèle DoS

Description OWASP: La surcharge des LLM avec des opérations gourmandes en ressources peut entraîner des interruptions de service et une augmentation des coûts. Référence ici.

Exemple: Un adversaire peut envoyer des messages complexes qui consomment des ressources informatiques excessives.

Prompt:

Exemple de réponse:

Opportunité de règle de détection :

FROM azure-openai-logs
| WHERE @timestamp > NOW() -  1 DAY
| WHERE response.choices LIKE "*requires*significant*computational*resources*"
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
| WHERE total_attempts >= 2

Cette détection illustre un autre exemple simple de l'utilisation de la réponse LLM pour identifier un comportement potentiellement abusif. Bien que cet exemple ne représente pas une menace traditionnelle pour la sécurité, il pourrait illustrer la manière dont les adversaires peuvent imposer des coûts aux victimes, en consommant des ressources ou des jetons.

Exemple 2: Un adversaire peut envoyer des messages complexes qui consomment des ressources informatiques excessives.

Prompt:

Exemple de réponse:

À première vue, cette invite semble bénigne. Cependant, des demandes excessives et des réponses verbeuses dans un court laps de temps peuvent augmenter les coûts de manière significative.

Opportunité de règle de détection:

FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 HOUR
| STATS request_count = COUNT(*), distinct_prompts = COUNT_DISTINCT(request.messages.content) BY connectorId
| WHERE request_count > 50 AND distinct_prompts > 10
| SORT request_count DESC

Dans le contexte de l'exemple 2, cette requête de travail permet de suivre et d'analyser efficacement les schémas d'utilisation en comptabilisant toutes les demandes et tous les contenus d'invite distincts pour chaque site connectorId à partir du site azure-openai-logs au cours de l'heure écoulée. Si un site connectorId soumet plus de 50 requêtes avec plus de dix invites uniques dans ce laps de temps, cela indique un schéma d'utilisation abusive potentiel comme celui décrit, où un adversaire pourrait modifier les requêtes pour sonder les détails de l'algorithme de cryptage, ce qui pourrait causer une charge indue ou échapper aux systèmes de détection. Les résultats sont ensuite classés par ordre de priorité sur le site connectorIds avec le plus grand nombre de requêtes, ce qui permet d'identifier rapidement les sources les plus actives ou les plus suspectes.

LLM06 - divulgation d'informations sensibles

Description de l'OWASP: L'absence de protection contre la divulgation d'informations sensibles dans les résultats du programme LLM peut avoir des conséquences juridiques ou entraîner la perte d'un avantage concurrentiel. Référence ici.

Exemple: Un adversaire peut créer des invites pour extraire des informations sensibles contenues dans les données d'apprentissage.

Prompt:

Exemple de réponse:

Opportunité de règle de détection :

FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE request.messages.content LIKE "*common*passwords*used*in*the*dataset*" AND malicious
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
 BY identified_threats.keyword, analysis.langkit_score
| WHERE total_attempts >= 2

Cette requête recherche les journaux du dernier jour qui contiennent des demandes portant spécifiquement sur "mots de passe courants utilisés dans l'ensemble de données" pour former le modèle et où ces demandes sont signalées comme étant malveillantes. Il regroupe ces journaux pour compter le nombre de ces tentatives et identifier les différents utilisateurs concernés, regroupés en fonction des menaces identifiées et du score du kit linguistique. Avec un certain enrichissement, l'inclusion de AND malicious = true permet de se concentrer sur les demandes déjà signalées comme potentiellement nuisibles, ce qui aide à hiérarchiser les actions d'investigation et de réponse.

Enrichir les règles de détection avec des informations sur la sécurité

En acheminant les requêtes LLM par l'intermédiaire d'un proxy, nous pouvons capitaliser sur des outils de sécurité spécialisés pour analyser chaque requête à la recherche de signes d'intention malveillante. En cas de détection, la demande initiale peut être enrichie de métadonnées supplémentaires indiquant la probabilité d'un contenu malveillant et le type spécifique de menace qu'il représente. Ces données enrichies sont ensuite indexées dans Elasticsearch, créant ainsi un ensemble de données robuste pour la surveillance, l'alerte et l'analyse rétrospective. Grâce à cet enrichissement, les possibilités de détection du LLM évoquées dans la dernière section sont possibles.

Nous ne nous pencherons pas sur tous les outils disponibles, mais plusieurs outils à code source ouvert sont apparus pour offrir différentes approches de l'analyse et de la sécurisation des interactions LLM. Certains de ces outils s'appuient sur des modèles d'apprentissage automatique formés pour détecter les messages malveillants :

  • Rebuff(GitHub) : Utilise l'apprentissage automatique pour identifier et atténuer les tentatives d'ingénierie sociale, d'hameçonnage et d'autres activités malveillantes à travers les interactions LLM. Un exemple d'utilisation consiste à faire passer le contenu des requêtes par le moteur d'analyse de Rebuff et à marquer les requêtes avec un champ booléen "malicieux" en fonction des résultats.
  • LLM-Guard(GitHub) : Fournit un moteur basé sur des règles pour détecter des modèles nuisibles dans les requêtes LLM. LLM-Guard peut classer les menaces détectées en fonction de catégories prédéfinies, en enrichissant les demandes avec des classifications détaillées des menaces.
  • LangKit(GitHub) : Kit d'outils conçu pour surveiller et sécuriser les LLM, LangKit peut analyser le contenu des requêtes à la recherche de signes d'intrants adverses ou de comportements involontaires du modèle. Il offre des crochets pour l'intégration de fonctions d'analyse personnalisées.
  • Vigil-LLM(GitHub) : Se concentre sur la surveillance en temps réel et l'alerte pour les demandes LLM suspectes. L'intégration dans la couche proxy permet de signaler immédiatement les problèmes de sécurité potentiels et d'enrichir les données de la demande avec des scores de vigilance.
  • Open-Prompt Injection(GitHub) : Offre des méthodologies et des outils pour détecter les attaques par injection rapide, permettant d'enrichir les données des requêtes avec des indicateurs spécifiques de compromission liés aux techniques d'injection rapide.

Remarque : la plupart de ces outils nécessitent des appels/coûts supplémentaires auprès d'un LLM externe, et requièrent une infrastructure supplémentaire pour une chasse aux menaces efficace.

Un exemple simple d'implémentation utilisant LLM-guard et LangKit pourrait ressembler à ceci :

def analyze_and_enrich_request(
   prompt: str, response_text: str, error_response: Optional[dict] = None
) -> dict:
   """Analyze the prompt and response text for malicious content and enrich the document."""

   # LLM Guard analysis
   sanitized_prompt, results_valid_prompt, results_score_prompt = scan_prompt(
       input_scanners, prompt["content"]
   )
   (
       sanitized_response_text,
       results_valid_response,
       results_score_response,
   ) = scan_output(output_scanners, sanitized_prompt, response_text)

   # LangKit for additional analysis
   schema = injections.init()
   langkit_result = extract({"prompt": prompt["content"]}, schema=schema)

   # Initialize identified threats and malicious flag
   identified_threats = []

   # Check LLM Guard results for prompt
   if not any(results_valid_prompt.values()):
       identified_threats.append("LLM Guard Prompt Invalid")

   # Check LLM Guard results for response
   if not any(results_valid_response.values()):
       identified_threats.append("LLM Guard Response Invalid")

   # Check LangKit result for prompt injection
   prompt_injection_score = langkit_result.get("prompt.injection", 0)
   if prompt_injection_score > 0.4:  # Adjust threshold as needed
       identified_threats.append("LangKit Injection")

   # Identify threats based on LLM Guard scores
   for category, score in results_score_response.items():
       if score > 0.5:
           identified_threats.append(category)

   # Combine results and enrich document
   # llm_guard scores map scanner names to float values of risk scores,
   # where 0 is no risk, and 1 is high risk.
   # langkit_score is a float value of the risk score for prompt injection
   # based on known threats.
   enriched_document = {
       "analysis": {
           "llm_guard_prompt_scores": results_score_prompt,
           "llm_guard_response_scores": results_score_response,
           "langkit_score": prompt_injection_score,
       },
       "malicious": any(identified_threats),
       "identified_threats": identified_threats,
   }

   # Check if there was an error from OpenAI and enrich the analysis
   if error_response:
       code = error_response.get("code")
       filtered_categories = {
           category: info["filtered"]
           for category, info in error_response.get(
               "content_filter_result", {}
           ).items()
       }

       enriched_document["analysis"]["openai"] = {
           "code": code,
           "filtered_categories": filtered_categories,
       }
       if code == "ResponsibleAIPolicyViolation":
           enriched_document["malicious"] = True

   return enriched_document

Cette fonction pourrait être appelée pour chaque requête passant par le proxy, les données renvoyées étant ajoutées au document de requête avant d'être envoyées à Elasticsearch. Le résultat est un ensemble de données détaillé et exploitable qui capture les interactions brutes avec le LLM et fournit des informations de sécurité immédiates à intégrer dans nos règles de détection basées sur la demande et la réponse. Si l'on reprend l'exemple de l'injection rapide LLM01, la requête pourrait être modifiée de la manière suivante :

FROM azure-openai-logs
| WHERE @timestamp > NOW() - 1 DAY
| WHERE identified_threats.keyword == "LangKit Injection" OR analysis.langkit_score > 0.4
| stats total_attempts = count(*), users = count_distinct(connectorId) by identified_threats.keyword, analysis.langkit_score
| WHERE users == 1 and total_attempts >= 2

Comme vous pouvez le constater, les deux mécanismes de notation sont subjectifs et se fondent sur les résultats fournis par les outils d'analyse des messages libres. Cette requête filtre les journaux des derniers jours où la menace identifiée est "LangKit Injection" ou le score LangKit est supérieur à 0.4. Il calcule ensuite le nombre total de tentatives et compte le nombre d'utilisateurs uniques (agents) associés à chaque catégorie de menace identifiée et à chaque score LangKit, en filtrant pour n'inclure que les cas où un seul utilisateur est impliqué (users == 1) et où le nombre total de tentatives est égal ou supérieur à deux (total_attempts >= 2).

Grâce à ces outils supplémentaires, nous disposons d'une variété de champs de résultats d'analyse pour améliorer nos règles de détection. Dans ces exemples, nous avons expédié la plupart des données telles quelles par souci de simplicité. Cependant, dans un environnement de production, il est crucial de normaliser ces champs dans tous les outils et les réponses LLM à un schéma comme Elastic Common Schema (ECS). La normalisation des données en fonction du SCE améliore l'interopérabilité entre les différentes sources de données, simplifie l'analyse et rationalise la création de règles de sécurité plus efficaces et plus cohérentes.

Dans la deuxième partie de cette série, nous verrons comment nous avons adopté une approche plus formelle de la cartographie des champs ECS et des intégrations.

Options alternatives pour l'audit des candidatures au LLM

Si l'utilisation d'un proxy peut être simple, d'autres approches peuvent être mieux adaptées à une installation de production, par exemple :

Sans surprise, ces approches présentent des limites potentielles, comme le fait de ne pas ingérer nativement toutes les données générées par les outils d'analyse de sécurité LLM sans développer une logique personnalisée pour prendre en charge des outils tiers.

Tirer parti d'Elastic APM pour obtenir des informations approfondies sur les applications

Elastic APM offre une solution alternative pour surveiller les applications en temps réel, ce qui est essentiel pour détecter les goulets d'étranglement en matière de performances et identifier les requêtes ou les demandes problématiques. En intégrant Elastic APM, les utilisateurs obtiennent des informations détaillées sur les temps de transaction, les performances des requêtes de base de données, l'efficacité des appels d'API externes, etc. Cette visibilité complète permet d'aborder et de résoudre plus facilement et rapidement les problèmes de performance ou les erreurs. Contrairement à l'approche par proxy, l'APM ingère automatiquement dans Elastic des journaux concernant votre application, ce qui permet de créer des règles de détection de la sécurité basées sur les comportements observés dans vos données.

Utiliser OpenTelemetry pour améliorer l'observabilité

Pour les applications qui utilisent déjà OpenTelemetry, l'exploitation de son intégration avec Elastic APM peut améliorer l'observabilité sans nécessiter de modifications importantes de l'instrumentation. Cette intégration permet de capturer un large éventail de données télémétriques, y compris des traces et des mesures, qui peuvent être envoyées de manière transparente à Elastic Stack. Cette approche permet aux développeurs de continuer à utiliser des bibliothèques familières tout en bénéficiant des solides capacités de surveillance d'Elastic. La compatibilité d'OpenTelemetry avec de nombreux langages de programmation et sa prise en charge par le protocole natif d'Elastic (OTLP) facilitent la transmission directe des données, ce qui constitue une base solide pour la surveillance des systèmes distribués. Par rapport à l'exemple du proxy, cette approche permet d'ingérer les données de manière plus native qu'en maintenant un index indépendant et un mécanisme de journalisation vers Elastic.

LLM Audit avec Kibana

Comme pour l'écriture d'une logique personnalisée pour votre application LLM afin d'auditer et d'expédier des données, vous pouvez tester l'approche avec l'assistant AI d'Elastic. Si vous êtes à l'aise avec TypeScript, envisagez de déployer une instance Elastic locale à l'aide du Guide de démarrage de Kibana. Une fois la configuration terminée, accédez à l'assistant Elastic AI et configurez-le pour qu'il intercepte les demandes et les réponses LLM à des fins d'audit et d'analyse. Note : Cette approche suit principalement l'intégration LLM spécifique à Elastic par rapport à l'utilisation d'APM et d'autres intégrations ou d'un proxy pour suivre les applications tierces. Il ne doit être envisagé qu'à des fins d'expérimentation et de tests exploratoires.

Heureusement, Kibana est déjà instrumenté avec APM, donc si vous configurez un serveur APM, vous commencerez automatiquement à ingérer les logs de cette source (en configurant elastic.apm.active: true). Consultez le README pour plus de détails.

Réflexions finales

Alors que nous poursuivons notre exploration de l'intégration des pratiques de sécurité dans le cycle de vie des grands modèles de langage chez Elastic, il est clair que l'intégration de la sécurité dans les flux de travail LLM peut permettre de créer des applications plus sûres et plus fiables. Ces exemples fictifs, tirés de notre travail au cours de la OnWeek, illustrent comment quelqu'un peut détecter, alerter et trier les activités malveillantes de manière proactive, en s'appuyant sur les solutions de sécurité que les analystes jugent les plus intuitives et les plus efficaces.

Il convient également de noter qu'avec l'exemple de l'approche par proxy, nous pouvons incorporer un modèle pour détecter et prévenir activement les demandes. En outre, nous pouvons trier la réponse LLM avant de la renvoyer à l'utilisateur si nous avons identifié des menaces malveillantes. À ce stade, nous avons la possibilité d'étendre nos protections de sécurité pour couvrir une variété d'approches défensives. Dans ce cas, la frontière entre sécurité et performance est ténue, car chaque vérification supplémentaire prend du temps et entrave le flux conversationnel naturel auquel les utilisateurs s'attendent.

N'hésitez pas à consulter le proxy de démonstration à llm-detection-proxy et à l'adapter à vos besoins !

Nous sommes toujours intéressés par des cas d'utilisation et des flux de travail comme ceux-ci, alors comme toujours, contactez-nous via GitHub issues, discutez avec nous dans notre communauté Slack, et posez des questions dans nos forums de discussion.

La publication et la date de publication de toute fonctionnalité ou fonction décrite dans le présent article restent à la seule discrétion d'Elastic. Toute fonctionnalité ou fonction qui n'est actuellement pas disponible peut ne pas être livrée à temps ou ne pas être livrée du tout.

Partager cet article