Mika Ayenson, PhD

Incorporando segurança em fluxos de trabalho de LLM: abordagem proativa da Elastic

Explorando a abordagem inovadora da Elastic para integrar segurança ao ciclo de vida de LLMs para proteção contra vulnerabilidades com o Assistente de IA da Elastic.

Incorporação de segurança em fluxos de trabalho LLM: Abordagem proativa da Elastic

Concluímos recentemente um dos nossos eventos trimestrais Elastic OnWeek, que oferece uma semana única para explorar oportunidades fora do nosso cotidiano. Em linha com publicações recentes da OWASP e da NSA AISC, decidimos dedicar algum tempo às dez principais vulnerabilidades da OWASP para LLMs nativamente no Elastic. Neste artigo, abordamos algumas oportunidades para detectar atividades maliciosas de LLM com ES|QL, a saber:

  • LLM01: Injeção rápida
  • LLM02: Tratamento de saída inseguro
  • LLM04: Negação de serviço do modelo
  • LLM06: Divulgação de informações sensíveis

O Elastic oferece a capacidade de auditar aplicativos LLM em busca de comportamentos maliciosos; mostraremos uma abordagem com apenas quatro etapas:

  1. Interceptar e analisar as solicitações e respostas do LLM
  2. Enriquecimento de dados com resultados de análises específicas do LLM
  3. Enviando dados para o Elastic Security
  4. Escrevendo regras de detecção ES|QL que podem ser usadas posteriormente para responder

Essa abordagem reflete nossos esforços contínuos para explorar e implementar estratégias avançadas de detecção, incluindo o desenvolvimento de regras de detecção adaptadas especificamente para LLMs, ao mesmo tempo em que acompanhamos as tecnologias emergentes de IA generativa e os desafios de segurança. Com base nessa base, o ano passado marcou uma melhoria significativa em nosso conjunto de ferramentas e capacidade geral de continuar esse caminho proativo.

A Elastic lançou o AI Assistant for Security, apresentando como o parceiro de IA generativa aberta é alimentado pela Search AI Platform — uma coleção de ferramentas relevantes para o desenvolvimento de aplicativos de pesquisa avançada. Com suporte de aprendizado de máquina (ML) e inteligência artificial (IA), este Assistente de IA fornece fluxos de trabalho predefinidos poderosos, como resumo de alertas, sugestões de fluxo de trabalho, conversões de consultas e consultoria de integração de agentes. Recomendo fortemente que você leia mais sobre o Assistente de IA da Elastic sobre como os recursos abrangem perfeitamente a Observabilidade e a Segurança.

Podemos usar os recursos do AI Assistant como um aplicativo LLM de terceiros para capturar, auditar e analisar solicitações e respostas para maior conveniência e para executar experimentos. Depois que os dados estão em um índice, escrever detecções comportamentais neles se torna algo normal — também podemos aproveitar todo o mecanismo de detecção de segurança. Embora estejamos representando a atividade LLM do Elastic AI Assistant neste experimento, ela é usada apenas como um veículo para demonstrar a auditoria de aplicativos baseados em LLM. Além disso, essa abordagem de proxy é destinada a aplicativos de terceiros para enviar dados ao Elastic Security.

Podemos introduzir mecanismos de segurança no ciclo de vida do aplicativo interceptando a atividade do LLM ou aproveitando métricas observáveis do LLM. É prática comum lidar com ameaças baseadas em prompts implementando várias táticas de segurança:

  1. Entradas limpas: higienize e valide as entradas do usuário antes de alimentá-las ao modelo
  2. Moderação de conteúdo: use ferramentas OpenAI para filtrar prompts e saídas prejudiciais
  3. Limites de taxa e monitoramento: rastreie padrões de uso para detectar atividades suspeitas
  4. Permitir/Listas de bloqueio: Defina entradas aceitáveis ou proibidas para aplicativos específicos
  5. Engenharia de Prompt Seguro: Projete prompts pré-construídos que orientem o modelo em direção aos resultados pretendidos
  6. Gerenciamento de função do usuário: controle o acesso do usuário para evitar ações não autorizadas
  7. Educar os usuários finais: promover o uso responsável do modelo para mitigar riscos
  8. Red Teaming e monitoramento: teste vulnerabilidades e monitore continuamente saídas inesperadas
  9. Feedback HITL para treinamento de modelo: aprenda com problemas sinalizados e humanos no circuito para refinar o modelo ao longo do tempo
  10. Restringir acesso à API: limite o acesso ao modelo com base em necessidades específicas e verificação do usuário

Dois recursos poderosos fornecidos pela OpenAI e muitos outros implementadores de LLM são a capacidade de enviar IDs de usuários finais e verificar o conteúdo em relação a uma API de moderação, recursos que definem o padrão de segurança do LLM. O envio de IDs com hash junto com a solicitação original auxilia na detecção de abusos e fornece feedback direcionado, permitindo a identificação exclusiva do usuário sem enviar informações pessoais. Como alternativa, o endpoint de moderação do OpenAI ajuda os desenvolvedores a identificar conteúdo potencialmente prejudicial, como discurso de ódio, incentivo à automutilação ou violência, permitindo que eles filtrem esse conteúdo. Ele vai ainda mais longe ao detectar ameaças e intenções de automutilação.

Apesar de todas as recomendações e melhores práticas para proteção contra avisos maliciosos, reconhecemos que não existe uma solução única e perfeita. Ao usar recursos como a API do OpenAI, algumas dessas ameaças podem ser detectadas pelo filtro de conteúdo, que responderá com uma notificação de violação da política de uso:

Essa filtragem de conteúdo é benéfica para resolver muitos problemas; no entanto, ela não consegue identificar outras ameaças no contexto mais amplo do ambiente, do ecossistema de aplicativos ou de outros alertas que possam aparecer. Quanto mais pudermos integrar casos de uso de IA generativa em nossos recursos de proteção existentes, mais controle e possibilidades teremos para lidar com ameaças potenciais. Além disso, mesmo que as proteções do LLM estejam em vigor para impedir ataques rudimentares, ainda podemos usar o mecanismo de detecção para alertar e tomar futuras ações de correção em vez de bloquear ou permitir abusos silenciosamente.

Solicitações e configuração de proxy LLM

A solução de segurança ideal integra proteções adicionais diretamente no ecossistema do aplicativo LLM. Isso permite enriquecer alertas com o contexto completo em torno de solicitações e respostas. À medida que as solicitações são enviadas ao LLM, podemos interceptá-las e analisá-las em busca de possíveis atividades maliciosas. Se necessário, uma ação de resposta pode ser acionada para adiar chamadas HTTP subsequentes. Da mesma forma, inspecionar a resposta do LLM pode revelar mais sinais de comportamento malicioso.

Usar um proxy para lidar com essas interações oferece várias vantagens:

  • Facilidade de integração e gerenciamento: ao gerenciar o novo código de segurança em um aplicativo proxy dedicado, você evita incorporar lógica de segurança complexa diretamente no aplicativo principal. Essa abordagem minimiza as alterações necessárias na estrutura do aplicativo existente, permitindo uma manutenção mais fácil e uma separação mais clara entre segurança e lógica de negócios. O aplicativo principal só precisa ser reconfigurado para rotear suas solicitações LLM por meio do proxy.
  • Desempenho e escalabilidade: colocar o proxy em um servidor separado isola os mecanismos de segurança e ajuda a distribuir a carga computacional. Isso pode ser crucial ao expandir operações ou gerenciar tarefas que exigem alto desempenho, garantindo que o desempenho do aplicativo principal não seja afetado pelo processamento de segurança adicional.

Opção de início rápido: Proxy com Flask

Você pode usar proxy para conexões LLM de entrada e saída para uma configuração inicial mais rápida. Essa abordagem pode ser generalizada para outros aplicativos LLM criando um aplicativo Flask simples baseado em Python. Este aplicativo interceptaria a comunicação, analisaria os riscos de segurança e registraria informações relevantes antes de encaminhar a resposta.

Existem vários SDKs para se conectar ao Elasticsearch e manipular solicitações do OpenAI LLM. O repositório llm-detection-proxy fornecido demonstra os clientes Elastic e OpenAI disponíveis. Este snippet destaca a maior parte do proxy experimental em uma única rota 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,
       }
   })

Com o servidor Flask, você pode configurar o OpenAI Kibana Connector para usar seu proxy.

Como esse proxy para seu LLM está sendo executado localmente, as credenciais e as informações de conexão são gerenciadas fora do Elastic, e uma string vazia pode ser fornecida na seção de chave de API. Antes de prosseguir, geralmente é uma boa ideia testar sua conexão. É importante considerar outras implicações de segurança se você estiver pensando em implementar uma solução de proxy em um ambiente real — algo que este protótipo não considerou por questões de brevidade.

Agora podemos indexar nossas solicitações e respostas LLM e começar a escrever detecções nos dados disponíveis no índice azure-openai-logs criado neste experimento. Opcionalmente, poderíamos pré-processar os dados usando um pipeline de ingestão Elastic, mas neste exemplo artificial, podemos efetivamente escrever detecções com o poder do ES|QL.

Dados de solicitação/resposta do AzureOpenAI LLM de exemplo

Procuração Langsmith

Observação: o projeto Langsmith Proxy fornece um proxy dockerizado para suas APIs LLM. Embora ofereça uma solução minimizada, no momento em que este artigo foi escrito, ele não tinha recursos nativos para incorporar ferramentas de análise de segurança personalizadas ou integração direta com o Elastic Security.

O LangSmith Proxy foi projetado para simplificar a interação da API LLM. É um aplicativo sidecar que requer configuração mínima (por exemplo, URL da API LLM). Ele melhora o desempenho (cache, streaming) para cenários de alto tráfego. Ele usa NGINX para eficiência e suporta rastreamento opcional para rastreamento detalhado de interações LLM. Atualmente, ele funciona com OpenAI e AzureOpenAI, com suporte futuro planejado para outros LLMs.

Ataques potenciais do LLM e oportunidades de regras de detecção

É importante entender que, embora listas documentadas de proteções não acompanhem alguns LLMs, simplesmente tentar alguns desses prompts pode ser imediatamente negado ou resultar em banimento em qualquer plataforma usada para enviar o prompt. Recomendamos que você experimente com cautela e entenda o SLA antes de enviar qualquer prompt malicioso. Como esta exploração aproveita os recursos do OpenAI, recomendamos seguir as orientações do bugcrowd e criar uma conta de teste adicional usando seu endereço de e-mail @bugcrowdninja.com.

Aqui está uma lista de vários exemplos plausíveis para ilustrar oportunidades de detecção. Cada tópico do LLM inclui a descrição do OWASP, um exemplo de prompt, um documento de amostra, a oportunidade de detecção e possíveis ações que os usuários podem tomar se integrarem mecanismos de segurança adicionais em seu fluxo de trabalho.

Embora esta lista não seja extensa no momento, o Elastic Security Labs está atualmente realizando uma série de iniciativas para garantir o desenvolvimento futuro, e a formalização das regras continuará.

LLM01 - injeção rápida

Descrição OWASP: Manipular LLMs por meio de entradas elaboradas pode levar a acesso não autorizado, violações de dados e comprometimento da tomada de decisões. Referência aqui.

Exemplo: Um adversário pode tentar criar prompts que induzam o LLM a executar ações não intencionais ou revelar informações confidenciais. Observação: ferramentas como o promptmap estão disponíveis para gerar ideias criativas de injeção de prompts e automatizar o processo de teste.

Prompt:

Resposta de exemplo:

Oportunidade de regra de detecção: neste exemplo, o LLM respondeu recusando-se a manipular strings de conexão de banco de dados devido a riscos de segurança. Ele enfatiza a manutenção da privacidade das credenciais e sugere o uso de métodos seguros, como variáveis de ambiente ou cofres, para protegê-las.

Uma consulta de correspondência de indicadores muito frágil, mas básica, pode ter esta aparência:

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*"

Uma consulta um pouco mais avançada detecta mais de duas tentativas semelhantes no último dia.

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

Observe que há muitas abordagens para detectar prompts maliciosos e proteger respostas LLM. Confiar apenas nesses indicadores não é a melhor abordagem; no entanto, podemos melhorar gradualmente a detecção com enriquecimento adicional ou inúmeras tentativas de resposta. Além disso, se introduzirmos um ID em nossos documentos, podemos aprimorar ainda mais nossa consulta agregando tentativas com base no campo que se correlaciona a um usuário específico.

Exemplo 2: O efeito Crescendo é um ataque de fuga de presos realista em que um adversário manipula gradualmente um modelo de linguagem por meio de uma série de investigações aparentemente inocentes que mudam para pedir ao modelo que descreva cenários hipotéticos envolvendo acesso não autorizado e manipulação de sistemas seguros. Ao fazer isso, eles pretendem extrair métodos que possam potencialmente contornar as restrições de segurança do LLM.

Prompt:

Resposta de exemplo:

Com a análise adicional da filtragem do OpenAI, podemos detectar imediatamente a primeira ocorrência de abuso.

Oportunidade de Regra de Detecção:

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

No entanto, à medida que você continua usando o Efeito Crescendo, notamos que o pivô da conversa não é mais bloqueado após o filtro de conteúdo inicial do OpenAI. É importante entender que, mesmo que táticas como essa sejam difíceis de prevenir, ainda temos oportunidades de detectá-las.

Ferramentas de análise adicionais, como o LLM-Guard, detectam se a conversa é sensível, o que, neste caso, é impreciso. No entanto, isso sugere oportunidades potenciais de rastrear comportamento malicioso por meio de vários prompts. Observação: também podemos aproveitar as sequências EQL como uma alternativa a esta consulta ES|QL para ajudar a rastrear comportamentos em vários eventos.

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

Esta consulta detecta comportamento suspeito relacionado a coquetéis molotov em vários eventos analisando sequências de entradas de log associadas a um único usuário/sessão (identificado por connectorId). O núcleo de consulta filtra eventos com base em:

  • Correspondência de conteúdo: busca menções de "Molotov" no conteúdo da conversa (request.messages.content LIKE "*Molotov*")
  • **Violações de política: identifica tentativas bloqueadas pelos filtros de segurança do OpenAI (analysis.openai.code == "ResponsibleAIPolicyViolation"), indicando o início de comportamento potencialmente suspeito
  • Consideração de sinalizador malicioso: inclui registros onde o sistema sinalizou o conteúdo como malicioso (malicious == true), capturando menções potencialmente sutis ou variadas
  • Análise em nível de sessão: ao agrupar eventos por connectorId, ele analisa a sequência completa de tentativas dentro de uma sessão. Em seguida, ele calcula o número total de tentativas (attempts = count(*)) e a pontuação de sensibilidade mais alta (max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive)) em todas as tentativas naquela sessão
  • Sinalizando sessões de alto risco: filtra sessões com pelo menos uma tentativa (attempts >= 1) e uma pontuação de sensibilidade máxima superior a 0,5 (max_sensitivity > 0.5). Esse limite ajuda a focar em sessões em que os usuários discutiram persistentemente ou revelaram conteúdo potencialmente arriscado.

Ao analisar esses fatores em vários eventos dentro de uma sessão, podemos começar a construir uma abordagem para detectar um padrão de discussões crescentes, mesmo que eventos individuais não sejam sinalizados isoladamente.

LLM02 - tratamento de saída inseguro

Descrição OWASP: Negligenciar a validação de saídas LLM pode levar a explorações de segurança posteriores, incluindo execução de código que compromete sistemas e expõe dados. Referência aqui.

Exemplo: Um adversário pode tentar explorar o LLM para gerar saídas que podem ser usadas para scripts entre sites (XSS) ou outros ataques de injeção.

Prompt:

Resposta de exemplo:

Oportunidade de Regra de Detecção:

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

Esta pseudoconsulta detecta possível manipulação de saída insegura identificando respostas LLM contendo elementos de script ou tentativas de acesso a cookies, que são comuns em ataques de Cross-Site Scripting (XSS). É um shell que pode ser estendido por listas de permissão ou bloqueio para palavras-chave conhecidas.

LLM04 - modelo DoS

Descrição OWASP: Sobrecarregar LLMs com operações que exigem muitos recursos pode causar interrupções de serviço e aumento de custos. Referência aqui.

Exemplo: Um adversário pode enviar prompts complexos que consomem recursos computacionais excessivos.

Prompt:

Resposta de exemplo:

Oportunidade de regra de detecção:

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

Essa detecção ilustra outro exemplo simples de como a resposta do LLM é usada para identificar comportamento potencialmente abusivo. Embora este exemplo possa não representar uma ameaça de segurança tradicional, ele pode emular como os adversários podem impor custos às vítimas, consumindo recursos ou tokens.

Exemplo 2: Um adversário pode enviar prompts complexos que consomem recursos computacionais excessivos.

Prompt:

Resposta de exemplo:

À primeira vista, esse aviso parece ser benigno. No entanto, solicitações excessivas e respostas detalhadas em um curto espaço de tempo podem aumentar significativamente os custos.

Oportunidade de Regra de Detecção:

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

No contexto do exemplo 2, esta consulta de trabalho rastreia e analisa com eficiência os padrões de uso contando todas as solicitações e conteúdos de prompt distintos para cada connectorId do azure-openai-logs na última hora. Se qualquer connectorId enviar mais de 50 solicitações com mais de dez prompts exclusivos dentro desse período, isso indica um possível padrão de uso indevido como o descrito, em que um adversário pode estar modificando consultas para sondar detalhes do algoritmo de criptografia, potencialmente causando carga indevida ou evitando sistemas de detecção. Os resultados são então ordenados para priorizar os connectorIds com as maiores contagens de solicitações, o que ajuda a identificar rapidamente as fontes mais ativas ou suspeitas.

LLM06 - divulgação de informações sensíveis

Descrição OWASP: A falha em proteger contra a divulgação de informações confidenciais nos resultados do LLM pode resultar em consequências legais ou perda de vantagem competitiva. Referência aqui.

Exemplo: Um adversário pode criar prompts para extrair informações confidenciais incorporadas nos dados de treinamento.

Prompt:

Resposta de exemplo:

Oportunidade de regra de detecção:

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

Esta consulta procura logs do último dia que contenham solicitações perguntando especificamente sobre "senhas comuns usadas no conjunto de dados" para treinar o modelo e onde tais solicitações são sinalizadas como maliciosas. Ele agrega esses logs para contar o número dessas tentativas e identifica usuários distintos envolvidos, agrupados por quaisquer ameaças identificadas e pela pontuação do kit de linguagem. Com algum enriquecimento, a inclusão de AND malicious = true garante foco em solicitações já sinalizadas como potencialmente prejudiciais, ajudando a priorizar ações de investigação e resposta.

Enriquecendo regras de detecção com insights de segurança

Ao rotear solicitações LLM por meio de um proxy, podemos aproveitar ferramentas de segurança especializadas para analisar cada solicitação em busca de sinais de intenção maliciosa. Após a detecção, a solicitação original pode ser enriquecida com metadados adicionais indicando a probabilidade de conteúdo malicioso e o tipo específico de ameaça que ele representa. Esses dados enriquecidos são então indexados no Elasticsearch, criando um conjunto de dados robusto de monitoramento, alertas e análise retrospectiva. Com esse enriquecimento, as oportunidades de detecção de LLM da última seção são possíveis.

Não nos aprofundamos em todas as ferramentas disponíveis, mas várias ferramentas de código aberto surgiram para oferecer abordagens variadas para analisar e proteger interações de LLM. Algumas dessas ferramentas são apoiadas por modelos de aprendizado de máquina treinados para detectar prompts maliciosos:

  • Rebuff (GitHub): Utiliza aprendizado de máquina para identificar e mitigar tentativas de engenharia social, phishing e outras atividades maliciosas por meio de interações LLM. Um exemplo de uso envolve passar o conteúdo da solicitação pelo mecanismo de análise do Rebuff e marcar as solicitações com um campo booleano "malicioso" com base nas descobertas.
  • LLM-Guard (GitHub): Fornece um mecanismo baseado em regras para detectar padrões prejudiciais em solicitações LLM. O LLM-Guard pode categorizar ameaças detectadas com base em categorias predefinidas, enriquecendo solicitações com classificações detalhadas de ameaças.
  • LangKit (GitHub): Um kit de ferramentas projetado para monitorar e proteger LLMs, o LangKit pode analisar o conteúdo da solicitação em busca de sinais de entradas adversas ou comportamentos de modelo não intencionais. Ele oferece ganchos para integrar funções de análise personalizadas.
  • Vigil-LLM (GitHub): Concentra-se no monitoramento em tempo real e no alerta de solicitações suspeitas de LLM. A integração na camada de proxy permite a sinalização imediata de possíveis problemas de segurança, enriquecendo os dados da solicitação com pontuações de vigilância.
  • Open-Prompt Injection (GitHub): Oferece metodologias e ferramentas para detectar ataques de injeção de prompt, permitindo o enriquecimento de dados de solicitação com indicadores específicos de comprometimento relacionados a técnicas de injeção de prompt.

Observação: a maioria dessas ferramentas exige chamadas/custos adicionais para um LLM externo e exigiria mais infraestrutura para caçar ameaças de forma eficaz.

Um exemplo simples de implementação que usa LLM-guard e LangKit pode ser parecido com este:

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

Essa função pode ser chamada para cada solicitação que passa pelo proxy, com os dados retornados sendo anexados ao documento de solicitação antes de serem enviados ao Elasticsearch. O resultado é um conjunto de dados detalhado e acionável que captura as interações brutas com o LLM e fornece insights de segurança imediatos para incorporar em nossas regras de detecção com base na solicitação e na resposta. Fechando o círculo com o exemplo de injeção de prompt LLM01, a consulta poderia ser atualizada para algo como isto:

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

Como você pode ver, ambos os mecanismos de pontuação são subjetivos com base nos resultados retornados pelas ferramentas de análise de prompt de código aberto. Esta consulta filtra logs do dia anterior em que a ameaça identificada é "LangKit Injection" ou a pontuação do LangKit está acima de 0.4. Em seguida, ele calcula o total de tentativas e conta o número de usuários únicos (agentes) associados a cada categoria de ameaça identificada e pontuação do LangKit, filtrando para incluir apenas casos em que há um único usuário envolvido (users == 1) e o total de tentativas é de duas ou mais (total_attempts >= 2).

Com essas ferramentas adicionais, temos uma variedade de campos de resultados de análise disponíveis para melhorar nossas regras de detecção. Nestes exemplos, enviamos a maioria dos dados no estado em que se encontram para simplificar. No entanto, em um ambiente de produção, é crucial normalizar esses campos em todas as ferramentas e respostas LLM para um esquema como o Elastic Common Schema (ECS). A normalização de dados para ECS melhora a interoperabilidade entre diferentes fontes de dados, simplifica a análise e agiliza a criação de regras de segurança mais eficazes e coesas.

Na segunda parte desta série, discutiremos como adotamos uma abordagem mais formal para o mapeamento de campos e integrações do ECS.

Opções alternativas para auditoria de aplicação LLM

Embora usar um proxy possa ser simples, outras abordagens podem ser mais adequadas para uma configuração de produção; por exemplo:

Não é de surpreender que essas abordagens tenham possíveis limitações, como não ingerir nativamente todos os dados gerados pela ferramenta de análise de segurança LLM sem desenvolver uma lógica personalizada para dar suporte a ferramentas de terceiros.

Aproveitando o Elastic APM para insights aprofundados sobre aplicativos

O Elastic APM fornece uma solução alternativa para monitorar aplicativos em tempo real, essencial para detectar gargalos de desempenho e identificar solicitações ou consultas problemáticas. Ao integrar o Elastic APM, os usuários obtêm insights detalhados sobre tempos de transação, desempenho de consultas ao banco de dados, eficiência de chamadas de API externas e muito mais. Essa visibilidade abrangente facilita o tratamento e a resolução rápida de problemas de desempenho ou erros. Diferentemente da abordagem de proxy, o APM ingere automaticamente logs no Elastic sobre seu aplicativo, oferecendo uma oportunidade de criar regras de detecção de segurança com base nos comportamentos observados em seus dados.

Utilizando OpenTelemetry para maior observabilidade

Para aplicativos que já empregam o OpenTelemetry, aproveitar sua integração com o Elastic APM pode melhorar a observabilidade sem exigir grandes mudanças na instrumentação. Essa integração oferece suporte à captura de uma ampla gama de dados de telemetria, incluindo rastros e métricas, que podem ser enviados facilmente para o Elastic Stack. Essa abordagem permite que os desenvolvedores continuem usando bibliotecas familiares enquanto se beneficiam dos recursos robustos de monitoramento do Elastic. A compatibilidade do OpenTelemetry com diversas linguagens de programação e seu suporte por meio do protocolo nativo da Elastic (OTLP) facilitam a transmissão direta de dados, fornecendo uma base sólida para o monitoramento de sistemas distribuídos. Comparado ao exemplo do proxy, essa abordagem ingere dados de forma mais nativa do que manter um índice independente e um mecanismo de registro no Elastic.

Auditoria LLM com Kibana

Assim como escrever lógica personalizada para seu aplicativo LLM para auditar e enviar dados, você pode testar a abordagem com o Assistente de IA da Elastic. Se você se sentir confortável com o TypeScript, considere implantar uma instância local do Elastic usando o Guia de primeiros passos do Kibana. Após a configuração, navegue até o Elastic AI Assistant e configure-o para interceptar solicitações e respostas do LLM para auditoria e análise. Observação: essa abordagem rastreia principalmente a integração LLM específica do Elastic em comparação ao uso do APM e outras integrações ou um proxy para rastrear aplicativos de terceiros. Deve ser considerado apenas para fins de experimentação e testes exploratórios.

Felizmente, o Kibana já está instrumentado com APM, então se você configurar um servidor APM, você começará automaticamente a ingerir logs dessa fonte (definindo elastic.apm.active: true). Veja o README para mais detalhes.

Considerações Finais

À medida que continuamos com essa exploração sobre a integração de práticas de segurança no ciclo de vida de grandes modelos de linguagem na Elastic, fica claro que incorporar segurança aos fluxos de trabalho de LLM pode fornecer um caminho a seguir para a criação de aplicativos mais seguros e confiáveis. Esses exemplos artificiais, extraídos do nosso trabalho durante a OnWeek, ilustram como alguém pode detectar, alertar e triar proativamente atividades maliciosas, aproveitando as soluções de segurança que os analistas consideram mais intuitivas e eficazes.

Também vale a pena notar que, com a abordagem de proxy de exemplo, podemos incorporar um modelo para detectar e prevenir solicitações ativamente. Além disso, podemos triar a resposta do LLM antes de enviá-la de volta ao usuário se tivermos identificado ameaças maliciosas. Neste ponto, temos a flexibilidade de estender nossas proteções de segurança para cobrir uma variedade de abordagens defensivas. Nesse caso, há uma linha tênue entre segurança e desempenho, pois cada verificação adicional consumirá tempo e impedirá o fluxo natural de conversação que os usuários esperariam.

Sinta-se à vontade para conferir o proxy de prova de conceito em llm-detection-proxy e adaptá-lo para atender às suas necessidades!

Estamos sempre interessados em ouvir casos de uso e fluxos de trabalho como esses, então, como sempre, entre em contato conosco por meio de problemas do GitHub, converse conosco em nossa comunidade Slack e faça perguntas em nossos fóruns de discussão.

O lançamento e o tempo de amadurecimento de todos os recursos ou funcionalidades descritos neste artigo permanecem a exclusivo critério da Elastic. Os recursos ou funcionalidades não disponíveis no momento poderão não ser entregues ou não chegarem no prazo previsto.

Compartilhe este artigo