Mika Ayenson 博士

将安全性嵌入 LLM 工作流程:Elastic 的积极主动方法

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

Embedding Security in LLM Workflows: Elastic's Proactive Approach

我们最近结束了季度性的 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 量身定制的检测规则,同时跟上新兴的生成式 AI 技术和安全挑战的步伐。在此基础上,去年标志着我们的工具包和整体能力的显著增强,以继续推进这一积极主动的道路。

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

我们可以使用 AI 助手的强大功能作为第三方 LLM 应用程序来捕获、审计和分析请求和响应,以方便和进行实验。一旦数据进入索引,对其编写行为检测就变得像往常一样 — 我们还可以利用整个安全检测引擎。即使我们在此实验中代理 Elastic AI 助手 LLM 活动,它也仅用作演示审计基于 LLM 的应用程序的工具。此外,此代理方法旨在供第三方应用程序将数据发送到 Elastic Security

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

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

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

尽管有所有保护恶意提示的建议和最佳实践,但我们认识到没有单一完美的解决方案。当使用像 OpenAI 的 API 这样的功能时,内容过滤器可能会检测到其中一些威胁,并回复使用政策违规通知

此内容过滤有利于解决许多问题;但是,它无法在更广泛的环境、应用程序生态系统或可能出现的其他警报中识别其他威胁。我们越能将生成式 AI 用例集成到我们现有的保护功能中,我们就越能控制和拥有解决潜在威胁的可能性。此外,即使 LLM 安全措施到位以阻止基本的攻击,我们仍然可以使用检测引擎来警报并采取未来的补救措施,而不是静默阻止或允许滥用。

代理 LLM 请求和设置

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

使用代理处理这些交互具有以下几个优点

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

快速入门选项:使用 Flask 的代理

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

存在多个 SDK 用于连接到 Elasticsearch 和处理 OpenAI LLM 请求。提供的 llm-detection-proxy 存储库演示了可用的 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 代理项目为您的 LLM API 提供了一个 Docker 化代理。虽然它提供了一个最小化的解决方案,但截至撰写本文时,它缺乏合并自定义安全分析工具或直接与 Elastic Security 集成的原生功能。

LangSmith 代理旨在简化 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 之类的工具来生成创造性的提示注入想法并自动化测试过程。

提示:

示例响应:

检测规则机会:在此示例中,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 安全约束的方法。

提示:

示例响应:

通过 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 效应时,我们会注意到在 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),捕获潜在的细微或不同的提及
  • 会话级别分析:通过按 connectorId 对事件进行分组,它会分析会话中尝试的完整序列。 然后,它计算尝试的总次数(attempts = count(*))以及该会话中所有尝试的最高敏感度得分(max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive)
  • 标记高风险会话:它过滤至少一次尝试的会话(attempts >= 1)和最大敏感度得分超过 0.5 的会话(max_sensitivity > 0.5)。 此阈值有助于关注用户持续讨论或泄露潜在风险内容的会话。

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

LLM02 - 不安全输出处理

OWASP 描述:忽略验证 LLM 输出可能会导致下游安全漏洞,包括破坏系统和暴露数据的代码执行。 请参考此处

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

提示:

示例响应:

检测规则机会:

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) 攻击中很常见。 它是一个外壳,可以通过众所周知的关键字的允许或阻止列表进行扩展。

LLM04 - 模型 DoS

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

示例:攻击者可能会发送消耗大量计算资源的复杂提示。

提示:

示例响应:

检测规则机会

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:攻击者可能会发送消耗大量计算资源的复杂提示。

提示:

示例响应:

乍一看,此提示似乎是良性的。 但是,短时间内过多的请求和冗长的响应会显着增加成本。

检测规则机会:

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 输出中敏感信息的泄露可能会导致法律后果或失去竞争优势。 请参考此处

示例:攻击者可能会精心设计提示,以提取嵌入在训练数据中的敏感信息。

提示:

示例响应:

检测规则机会

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

此查询搜索过去一天内,包含明确询问“用于训练模型的 数据集中使用的常见密码”的请求的日志,并且这些请求被标记为恶意。它会聚合这些日志以计算此类尝试的次数,并识别涉及的不同用户,按任何已识别的威胁和语言工具包 (LangKit) 分数进行分组。通过一些增强,包含 AND malicious = true 确保关注已被标记为可能有害的请求,从而有助于优先进行调查和响应操作。

使用安全洞察增强检测规则

通过将 LLM 请求路由通过代理,我们可以利用专业的安全工具来分析每个请求,以查找恶意意图的迹象。一旦检测到,原始请求可以使用额外的元数据进行增强,以指示恶意内容的可能性及其代表的具体威胁类型。然后,将此增强的数据索引到 Elasticsearch 中,创建一个强大的监控、警报和回顾性分析数据集。通过这种增强,上一节中描述的 LLM 检测机会成为可能。

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

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

注意:这些工具中的大多数都需要对外部 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 助手并将其配置为拦截 LLM 请求和响应,以进行审计和分析。注意:与使用 APM 和其他集成或代理来跟踪第三方应用程序相比,此方法主要跟踪 Elastic 特定的 LLM 集成。它应该仅用于实验和探索性测试目的。

幸运的是,Kibana 已经使用 APM 进行了检测,因此,如果您配置了 APM 服务器,您将自动开始从此源摄取日志(通过设置 elastic.apm.active: true)。有关更多详细信息,请参阅 README

结束语

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

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

请随时查看 llm-detection-proxy 中的概念验证代理,并根据您的需要进行调整!

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

本帖子中描述的任何特性或功能的发布和时间安排均由 Elastic 自行决定。任何当前不可用的特性或功能都可能无法按时交付或根本不交付。