Mika Ayenson, PhD

在 LLM 工作流中嵌入安全性:Elastic 的主动方法

探索 Elastic 将安全性集成到 LLM 生命周期的创新方法,以防范 Elastic 的 AI 助手的漏洞。

阅读时间:28 分钟检测科学机器学习生成人工智能
在 LLM 工作流中嵌入安全性:Elastic 的主动方法

我们最近结束了每季度一次的 Elastic OnWeek 活动之一,该活动提供了一个独特的一周来探索日常工作之外的机会。 根据OWASPNSA AISC最近发布的消息,我们决定花一些时间研究 Elastic 中原生的 LLM 的 OWASP 十大漏洞。 在本文中,我们讨论了一些使用ES|QL检测恶意 LLM 活动的机会,即:

  • LLM01:即时注射
  • LLM02:不安全的输出处理
  • LLM04:模型拒绝服务
  • LLM06:敏感信息披露

Elastic 提供了审核 LLM 应用程序是否存在恶意行为的功能;我们将向您展示一种仅需四个步骤的方法:

  1. 拦截并分析 LLM 请求和响应
  2. 利用 LLM 特定的分析结果丰富数据
  3. 发送数据至 Elastic Security
  4. 编写 ES|QL 检测规则,稍后可用于响应

这种方法反映了我们不断探索和实施先进检测策略的努力,包括制定专门针对 LLM 的检测规则,同时跟上新兴的生成式人工智能技术和安全挑战。 在此基础上,去年我们的工具包和整体能力得到了显著提升,继续沿着这条积极主动的道路前进。

Elastic发布了安全 AI 助手,介绍了开放式生成 AI 助手如何由搜索 AI 平台(一套用于开发高级搜索应用程序的相关工具)提供支持。 在机器学习 (ML) 和人工智能 (AI) 的支持下,该 AI 助手提供了强大的预构建工作流程,如警报摘要、工作流程建议、查询转换和代理集成建议。 我强烈建议您阅读有关 Elastic 的AI 助手的更多信息,了解这些功能如何无缝跨越可观察性和安全性。

我们可以使用 AI Assistant 的功能作为第三方 LLM 应用程序来捕获、审核和分析请求和响应,以方便运行实验。 一旦数据进入索引,在其上写入行为检测就成为常态——我们还可以利用整个安全检测引擎。 尽管我们在这个实验中代理了 Elastic AI Assistant LLM 活动,但它仅仅被用作演示审计基于 LLM 的应用程序的工具。 此外,此代理方法旨在让第三方应用程序将数据传送到Elastic Security

我们可以通过拦截 LLM 活动或利用可观察的 LLM 指标将安全机制引入应用程序的生命周期。 通过实施各种安全策略来解决基于提示的威胁是一种常见的做法:

  1. 清理输入:在将用户输入输入到模型之前对其进行清理和验证
  2. 内容审核:使用 OpenAI 工具过滤有害的提示和输出
  3. 速率限制和监控:跟踪使用模式以检测可疑活动
  4. 允许/阻止列表:为特定应用程序定义可接受或禁止的输入
  5. 安全提示工程:设计预建提示,引导模型实现预期结果
  6. 用户角色管理:控制用户访问以防止未经授权的操作
  7. 教育最终用户:促进负责任地使用模型以降低风险
  8. 红队与监控:测试漏洞并持续监控意外输出
  9. 模型训练的 HITL 反馈:从人机交互中学习,标记问题,随着时间的推移完善模型
  10. 限制 API 访问:根据特定需求和用户验证限制模型访问

OpenAI 和许多其他 LLM 实施者提供的两个强大功能是提交最终用户 ID和根据审核 API检查内容的能力,这些功能为 LLM 安全性设定了标准。 与原始请求一起发送散列 ID 有助于检测滥用并提供有针对性的反馈,从而无需发送个人信息即可实现唯一的用户识别。 另外,OpenAI 的审核端点可以帮助开发人员识别潜在有害的内容,如仇恨言论、鼓励自残或暴力,从而允许他们过滤此类内容。 它甚至可以更进一步检测威胁和自残意图。

尽管有各种建议和最佳实践来防止恶意提示,但我们认识到没有单一的完美解决方案。 当使用 OpenAI 的 API 等功能时,内容过滤器可能会检测到其中一些威胁,并会使用违反政策通知进行响应:

这种内容过滤有助于解决许多问题;但是,它无法在更广泛的环境、应用生态系统或可能出现的其他警报中识别进一步的威胁。 我们越能将生成式人工智能用例融入到我们现有的保护能力中,我们应对潜在威胁的控制力和可能性就越大。 此外,即使已经采取了 LLM 保护措施来阻止基本的攻击,我们仍然可以使用检测引擎来发出警报并采取未来的补救措施,而不是默默地阻止或允许滥用。

代理 LLM 请求和设置

最佳安全解决方案将额外的保护措施直接集成在 LLM 应用程序的生态系统中。 这允许使用围绕请求和响应的完整上下文来丰富警报。 当请求发送到 LLM 时,我们可以拦截并分析它们以发现潜在的恶意活动。 如果有必要,可以触发响应操作来推迟后续的 HTTP 调用。 同样,检查 LLM 的回应可以发现更多恶意行为的迹象。

使用代理来处理这些交互有几个优点:

  • 易于集成和管理:通过在专用代理应用程序中管理新的安全代码,您可以避免将复杂的安全逻辑直接嵌入到主应用程序中。 这种方法最大限度地减少了现有应用程序结构所需的更改,从而更容易维护并且更明确地将安全性与业务逻辑分开。 仅需重新配置主应用程序即可通过代理路由其 LLM 请求。
  • 性能和可扩展性:将代理放在单独的服务器上可以隔离安全机制并有助于分配计算负载。 在扩大操作或管理性能密集型任务时,这一点至关重要,确保主应用程序的性能不受额外安全处理的影响。

快速启动选项:使用 Flask 代理

您可以代理传入和传出的 LLM 连接,以加快初始设置。 通过创建一个简单的基于 Python 的Flask应用程序,可以将此方法推广到其他 LLM 应用程序。 该应用程序将拦截通信,分析其安全风险,并在转发响应之前记录相关信息。

存在多个 SDK 来连接到 Elasticsearch 并处理 OpenAI LLM 请求。 提供的llm-detection-proxy repo 演示了可用的 Elastic 和 OpenAI 客户端。 此代码片段突出显示了单个 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,
       }
   })

使用 Flask 服务器,您可以配置OpenAI Kibana 连接器以使用您的代理。

由于您的 LLM 的此代理在本地运行,因此凭据和连接信息在 Elastic 之外进行管理,并且可以在 API 密钥部分提供一个空字符串。 在继续之前,测试您的连接通常是一个好主意。 如果您正在考虑在真实环境中实施代理解决方案,那么考虑其他安全影响非常重要 - 为了简洁起见,此原型并未考虑到这一点。

我们现在可以索引我们的 LLM 请求和响应,并开始在此实验中创建的azure-openai-logs索引中的可用数据上写入检测。 或者,我们可以使用 Elastic摄取管道预处理数据,但在这个虚构的示例中,我们可以使用 ES|QL 的功能有效地编写检测。

AzureOpenAI LLM 请求/响应数据示例

Langsmith 代理

注意: Langsmith Proxy项目为您的 LLM API 提供了一个 dockerized 代理。 虽然它提供了一个最小化的解决方案,但截至撰写本文时,它缺乏合并自定义安全分析工具或直接与 Elastic Security 集成的本机功能。

LangSmith Proxy 旨在简化 LLM API 交互。 它是一个需要最少配置(例如 LLM API URL)的附加应用程序。 它增强了高流量场景的性能(缓存、流式传输)。 它使用 NGINX 来提高效率,并支持可选跟踪以进行详细的 LLM 交互跟踪。 目前,它与 OpenAI 和 AzureOpenAI 合作,未来计划支持其他 LLM。

LLM 潜在攻击和检测规则机会

重要的是要理解,即使某些 LLM 没有附带记录的保护列表,但仅仅尝试其中一些提示可能会立即被拒绝或导致在用于提交提示的任何平台上被禁止。 我们建议在发送任何恶意提示之前谨慎尝试并了解 SLA。 由于此次探索利用了 OpenAI 的资源,我们建议遵循 bugcrowd指导并使用您的 @bugcrowdninja.com 电子邮件地址注册一个额外的测试帐户。

这里列出了几个合理的例子来说明检测机会。 每个 LLM 主题都包含 OWASP 描述、示例提示、示例文档、检测机会以及用户在其工作流程中集成其他安全机制时可能采取的潜在行动。

虽然目前这个列表并不详尽,但 Elastic Security Labs 目前正在采取多项举措,以确保未来的发展,并且规则的正式化将继续下去。

LLM01——即时注射

OWASP 描述:通过精心设计的输入操纵 LLM 可能导致未经授权的访问、数据泄露和决策受损。 参考这里

示例:对手可能会尝试制作提示,诱骗 LLM 执行非预期的操作或泄露敏感信息。 注:可以使用promptmap之类的工具来生成有创意的提示注入想法并自动化测试过程。

Prompt:

示例响应

检测规则机会:在此示例中,LLM 由于安全风险而拒绝处理数据库连接字符串。 它强调保持凭证的私密性并建议使用环境变量或保险库等安全方法来保护它们。

一个非常脆弱但基本的指标匹配查询可能看起来像这样:

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

稍微高级一点的查询可以检测到过去一天内两次以上的类似尝试。

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

请注意,有很多方法可以检测恶意提示并保护 LLM 响应。 仅仅依靠这些指标并不是最好的方法;然而,我们可以通过额外的丰富或多次响应尝试来逐步改善检测。 此外,如果我们在文档中引入 ID,我们可以通过根据与特定用户相关的字段聚合尝试来进一步增强查询。

示例 2Crescendo效应是一种逼真的越狱攻击,其中攻击者通过一系列看似无辜的询问逐渐操纵语言模型,这些询问转向要求模型描述涉及未经授权访问和操纵安全系统的假设场景。 通过这样做,他们的目的是提取可能绕过 LLM 安全限制的方法。

Prompt:

示例响应

通过 OpenAI 过滤的附加分析,我们可以立即检测到第一次滥用行为。

检测规则机会

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

然而,随着你继续使用 Crescendo Effect,我们注意到在 OpenAI 进行初始内容过滤之后,对话枢纽已经不再受阻。 重要的是要明白,即使这样的策略很难预防,我们仍然有机会发现。

LLM-Guard 等附加分析工具可以检测对话是否敏感,但在这种情况下,这是不准确的。 然而,它暗示了通过多个提示追踪恶意行为的潜在机会。 注意:我们还可以利用 EQL 序列作为此 ES|QL 查询的替代,以帮助跟踪多个事件的行为。

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

此查询通过分析与单个用户/会话(由connectorId标识)相关的日志条目序列,检测多个事件中与莫洛托夫鸡尾酒有关的可疑行为。 查询核心根据以下内容过滤事件:

  • 内容匹配:在对话内容中搜索“Molotov”的提及 ( request.messages.content LIKE "*Molotov*" )
  • **违反政策:它识别被 OpenAI 安全过滤器 ( analysis.openai.code == "ResponsibleAIPolicyViolation" ) 阻止的尝试,表明潜在可疑行为的开始
  • 恶意标记考虑:它包括系统将内容标记为恶意 ( malicious == true ) 的日志,捕获潜在的微妙或不同的提及
  • 会话级分析:通过按连接器 ID 对事件进行分组,分析会话内的完整尝试序列。 然后,它会计算该会话中尝试的总次数 ( attempts = count(*) ) 以及所有尝试中的最高敏感度分数 ( max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive) )
  • 标记高风险会话:过滤至少有一次尝试( attempts >= 1 )且最大敏感度分数超过 0.5( max_sensitivity > 0.5 )的会话。 此阈值有助于关注用户持续讨论或透露潜在危险内容的会话。

通过分析会话中多个事件的这些因素,我们可以开始建立一种方法来检测不断升级的讨论模式,即使单个事件可能不会被单独标记。

LLM02——不安全的输出处理

OWASP 描述:忽视验证 LLM 输出可能会导致下游安全漏洞,包括危害系统和暴露数据的代码执行。 参考这里

示例:对手可能试图利用 LLM 生成可用于跨站点脚本 (XSS) 或其他注入攻击的输出。

Prompt:

示例响应

检测规则机会

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

该伪查询通过识别包含脚本元素或 cookie 访问尝试的 LLM 响应来检测潜在的不安全输出处理,这些响应在跨站点脚本 (XSS) 攻击中很常见。 它是一个可以通过知名关键字的允许或阻止列表进行扩展的 shell。

LLM04——模型 DoS

OWASP 描述:使用资源密集型操作使 LLM 超载可能会导致服务中断和成本增加。 参考这里

示例:对手可能会发送复杂的提示,消耗过多的计算资源。

Prompt:

示例响应

检测规则机会:

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

此检测说明了如何使用 LLM 响应来识别潜在滥用行为的另一个简单示例。 虽然这个例子可能并不代表传统的安全威胁,但它可以模拟对手如何对受害者施加成本,无论是消耗资源还是代币。

示例 2 :对手可能会发送复杂的提示,消耗过多的计算资源。

Prompt:

示例响应

乍一看,这个提示似乎是良性的。 然而,短时间内过多的请求和冗长的回复会显著增加成本。

检测规则机会

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

在示例 2 的上下文中,此工作查询通过计算过去一小时内来自azure-openai-logs的每个connectorId的所有请求和不同提示内容,有效地跟踪和分析使用模式。 如果任何connectorId在此时间范围内提交超过 50 个请求,且包含超过 10 个唯一提示,则表明存在潜在的滥用模式,例如上述模式,对手可能会修改查询以探测加密算法详细信息,从而可能导致过度负载或逃避检测系统。 然后对结果进行排序,优先考虑请求数最高的connectorIds ,这有助于快速识别最活跃或最可疑的来源。

LLM06 - 敏感信息披露

OWASP 描述:未能防止 LLM 输出中的敏感信息泄露可能导致法律后果或丧失竞争优势。 参考这里

示例:对手可能会精心设计提示来提取训练数据中嵌入的敏感信息。

Prompt:

示例响应

检测规则机会:

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

此查询搜索过去一天的日志,其中包含专门询问“数据集中使用的常用密码”以训练模型的请求,并且此类请求被标记为恶意。 它汇总这些日志以计算此类尝试的次数,并识别所涉及的不同用户,并根据已识别的威胁和语言工具包分数进行分组。 通过一些丰富功能,加入AND malicious = true可确保重点关注已被标记为潜在有害的请求,从而帮助确定调查和响应行动的优先顺序。

利用安全洞察丰富检测规则

通过代理路由 LLM 请求,我们可以利用专门的安全工具来分析每个请求是否存在恶意的迹象。 检测后,原始请求可以通过附加元数据进行丰富,表明恶意内容的可能性以及它所代表的威胁的具体类型。 然后,这些丰富的数据在 Elasticsearch 中被编入索引,从而创建一个强大的监控、警报和回顾分析数据集。 通过这种丰富,上一节中的 LLM 检测机会成为可能。

我们不会深入研究每一种可用的工具,但已经出现了一些开源工具,提供了分析和保护 LLM 交互的不同方法。 其中一些工具由经过训练的机器学习模型支持,可以检测恶意提示:

  • RebuffGitHub ):利用机器学习通过 LLM 交互来识别和缓解社会工程、网络钓鱼和其他恶意活动的尝试。 示例用法包括将请求内容传递到 Rebuff 的分析引擎,并根据调查结果使用“恶意”布尔字段标记请求。
  • LLM-GuardGitHub ):提供基于规则的引擎,用于检测 LLM 请求中的有害模式。 LLM-Guard 可以根据预定义的类别对检测到的威胁进行分类,并通过详细的威胁分类丰富请求。
  • LangKitGitHub ):LangKit 是一个专为监控和保护 LLM 而设计的工具包,它可以分析请求内容以查找对抗性输入或非预期模型行为的迹象。 它提供了用于集成自定义分析功能的钩子。
  • Vigil-LLMGitHub ):专注于对可疑 LLM 请求进行实时监控和警报。 集成到代理层可以立即标记潜在的安全问题,并通过警戒分数丰富请求数据。
  • Open-Prompt InjectionGitHub ):提供检测提示注入攻击的方法和工具,允许使用与提示注入技术相关的特定危害指标来丰富请求数据。

注意:大多数这些工具都需要额外调用/支付外部 LLM 的费用,并且需要进一步的基础设施才能有效地搜寻威胁。

使用 LLM-guard 和 LangKit 的一个简单示例实现可能如下所示:

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

每个通过代理的请求都可以调用此函数,返回的数据将附加到请求文档中,然后再发送到 Elasticsearch。 结果是一个详细且可操作的数据集,它捕获与 LLM 的原始交互,并根据请求和响应提供即时的安全见解以嵌入到我们的检测规则中。 回到提示注入 LLM01 示例,查询可以更新为如下内容:

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

如您所见,这两种评分机制都是主观的,基于开源提示分析工具返回的结果。 此查询会过滤过去一天的日志,其中所识别的威胁为“LangKit 注入”或 LangKit 分数高于0.4 。 然后,它计算总尝试次数,并计算与每个已识别威胁类别和 LangKit 分数相关的唯一用户(代理)的数量,并进行过滤以仅包含涉及单个用户( users == 1 )且总尝试次数为两次或更多( total_attempts >= 2 )的情况。

有了这些附加工具,我们就可以使用多种分析结果字段来改进我们的检测规则。 在这些示例中,为了简单起见,我们按原样发送了大部分数据。 然而,在生产环境中,对所有工具和 LLM 响应中的这些字段进行规范化以适应Elastic Common Schema (ECS) 之类的模式至关重要。 将数据规范化到 ECS 可增强不同数据源之间的互操作性、简化分析并简化更有效、更有凝聚力的安全规则的创建。

在本系列的第二部分中,我们将讨论如何采用更正式的方法进行 ECS 字段映射和集成。

LLM 申请审核的其他选项

虽然使用代理可能很简单,但其他方法可能更适合生产设置;例如:

  • 利用应用程序性能监控(APM)
  • 使用 OpenTelemetry 集成
  • 直接修改 Kibana 中的更改以审计和跟踪 LLM 活动

毫不奇怪,这些方法具有潜在的局限性,例如,如果不开发自定义逻辑来支持第三方工具,就无法本地提取生成的所有 LLM 安全分析工具数据。

利用 Elastic APM 获得深入的应用程序洞察

Elastic APM提供了一种实时监控应用程序的替代解决方案,对于检测性能瓶颈和识别有问题的请求或查询至关重要。 通过集成 Elastic APM,用户可以详细了解交易时间、数据库查询性能、外部 API 调用效率等。 这种全面的可见性使得快速解决性能问题或错误变得更加容易。 与代理方法不同,APM 会自动将有关您的应用程序的日志提取到 Elastic 中,从而提供根据数据中看到的行为创建安全检测规则的机会。

利用 OpenTelemetry 增强可观察性

对于已经采用 OpenTelemetry 的应用程序,利用其与 Elastic APM 的集成可以增强可观察性,而无需进行大量的仪器更改。 此集成支持捕获各种遥测数据,包括跟踪和指标,这些数据可以无缝发送到 Elastic Stack。 这种方法允许开发人员继续使用熟悉的库,同时受益于 Elastic 强大的监控功能。 OpenTelemetry 跨多种编程语言的兼容性及其通过 Elastic 原生协议 (OTLP) 的支持促进了简单的数据传输,为监控分布式系统提供了坚实的基础。 与代理示例相比,这种方法比维护独立的索引和日志记录机制到 Elastic 更原生地提取数据。

使用 Kibana 进行 LLM 审计

就像为您的 LLM 应用程序编写自定义逻辑来审核和发送数据一样,您可以使用 Elastic 的 AI 助手测试该方法。 如果您熟悉 TypeScript,请考虑使用 Kibana入门指南部署本地 Elastic 实例。 设置完成后,导航到Elastic AI Assistant并将其配置为拦截 LLM 请求和响应以进行审计和分析。 注意:与使用 APM 和其他集成或代理来跟踪第三方应用程序相比,此方法主要跟踪特定于 Elastic 的 LLM 集成。 它仅应被视为用于实验和探索性测试目的。

幸运的是,Kibana 已经配备了 APM,因此如果您配置了 APM 服务器,您将自动开始从该源提取日志(通过设置elastic.apm.active: true )。 请参阅自述文件以了解更多详细信息。

结束语

随着我们继续探索在 Elastic 大型语言模型的生命周期内集成安全实践,很明显,将安全性嵌入到 LLM 工作流中可以为创建更安全、更可靠的应用程序提供前进的道路。 这些人为的例子取自我们在 OnWeek 期间的工作,说明了如何利用分析师认为最直观、最有效的安全解决方案,主动检测、警报和分类恶意活动。

还值得注意的是,通过示例代理方法,我们可以结合模型来主动检测和阻止请求。 此外,如果我们发现恶意威胁,我们可以在将 LLM 响应发送回用户之前对其进行分类。 此时,我们可以灵活地扩展我们的安全保护以涵盖各种防御方法。 在这种情况下,安全性和性能之间存在着一条细线,因为每次额外的检查都会耗费时间并阻碍用户期望的自然对话流程。

请随意查看llm-detection-proxy上的概念验证代理,并使其适合您的需求!

我们始终对听到此类用例和工作流程感兴趣,因此,请一如既往地通过GitHub 问题与我们联系,在我们的社区 Slack中与我们聊天,并在我们的讨论论坛中提问。

本博文所描述的任何特性或功能的发布及上市时间均由 Elastic 自行决定。当前尚未发布的任何特性或功能可能无法按时提供或根本无法提供。