ITPub博客

首页 > 人工智能 > 自然语言 > 带堆视图的保险库:AgentCore Harness 与身份之间令人不安的空间

带堆视图的保险库:AgentCore Harness 与身份之间令人不安的空间

自然语言 作者:ITPUB社群 时间:1970-01-01 08:33:46 0 删除 编辑

执行摘要

Unit 42 研究人员发现了一个问题:在 Amazon Web Services (AWS) AgentCore Harness 中使用默认配置,可能允许攻击者通过提示注入操纵智能体的行为,从而窃取由 AgentCore Identity 管理的明文凭据。

为得出这一结论,我们检查了该 harness 众多集成中的两个:

  • AWS AgentCore Identity,平台推荐的用于管理智能体身份和存储凭据的方式(即身份保管库)

  • 下游 Model Context Protocol (MCP) 服务器,harness 使用来自该身份保管库的凭据对其进行身份验证

AWS AgentCore Identity 提供静态加密、传输中加密、密钥管理服务 (KMS) 密钥以及身份和访问管理 (IAM) 门控访问。我们想了解运行时会发生什么——当凭据必须离开保管库才能被使用时。我们发现,harness 自身内置的 shell 工具(默认启用)会进入凭据被解析为明文的同一内存空间。

我们向 AWS 披露了这一发现。AWS 审查后,根据 AgentCore 责任共担模型,将此报告作为信息性报告关闭,并指出 allowedTools 范围限定和出口过滤是客户侧控制措施。

对于当前基于 AgentCore 进行构建的运营人员,防御需要采取分层方法:

  • 将 harness 可使用的 allowedTools 限定为其所需范围

  • 将 Identity 保管库服务账号限定为下游集成的最小权限

  • 监控来自 harness 容器的出站流量

Palo Alto Networks 客户可通过以下产品和服务,更好地防御本文讨论的威胁:

  • Cortex Cloud

Unit 42 Cloud Security Assessment 是一项评估服务,用于审查云基础设施以识别错误配置和安全缺口。

如果您认为自己可能已遭到入侵或有紧急事项,请联系 Unit 42 事件响应团队。

| 相关 Unit 42 主题 | AgentCore、AWS、身份、AI 智能体 |
| --- | --- |

AgentCore Harness 背景介绍

以下研究完全基于 AWS AgentCore Harness,这是一个面向 AI 智能体的托管运行时。正如 AWS 所描述的,你只需声明智能体的功能(模型、工具、技能、指令),AgentCore 会处理其余的一切。这包括将配置转化为运行中智能体所需的环境、计算、内存、身份、网络和可观测性。

你所声明的只是其中一部分。在此之上,该 harness 还默认启用了两个内置工具。正如 AWS 在 2026 年 8 月下旬的文档中所述:

"默认工具 shell 和 file_operations 在每个会话中都可用,除非你通过 allowedTools 限制它们。shell 执行 bash 命令;file_operations 支持查看、创建和编辑文件。"

内置工具是使该 harness 如此自主且高效的重要原因。智能体可以编写文件并运行代码来完成实际工作。但正是这种使内置工具有用的广泛能力,在人们无意中将其保持开启时,也使其变得危险。

我们发现 shell 工具在 harness 内以 root 身份运行,因此一旦攻击者让智能体执行命令,该命令就会继承相同的 root 权限。这不需要任何错误配置就会发生。这是开箱即用的默认状态。

除非你将 allowedTools 参数限定为每个会话实际所需的范围,否则每个会话都可以运行任意 shell 命令并读写文件,无论你是否请求了这些工具。

智能体 Harness 弥合了推理与行动之间的鸿沟

不久前,AI 模型可以回答问题但无法据此采取行动。如今,AI 智能体正在跨越曾经遥不可及的边界进行推理,承担更复杂、运行时间更长且更自主的任务。

但仅靠推理无法让智能体走得很远。为了发挥作用,智能体需要将决策转化为行动的基础设施。

这正是智能体 harness 所填补的空白。它是模型周围的托管运行时,旨在让智能体保持正轨,并为其提供自主运行所需的一切。harness 提供多种不同的能力,包括以下内容:

  • 可调用的工具

  • 用于执行代码的沙箱化 shell

  • 跨会话持久化的记忆

  • 用于外部服务的 MCP 集成

  • 用于执行操作的身份

harness 在一个具备弹性的循环中编排这些能力,使智能体能够规划、行动、观察并继续执行。

下面的图 1 展示了智能体 harness 的解剖结构。

如图 1 所示,用户的可及范围止于“invoke”。而 harness 的可及范围则延伸至操作员凭据下的每一个工具和下游服务。

在 harness 能够赋予智能体的所有能力中,shell 工具既可能是显著的生产力提升手段,也可能是主要的攻击面。

但要想理解 shell 工具是如何出现的,我们首先需要快速回顾一下大语言模型在这类工具的语境中是如何工作的。

Shell 工具:优势与风险

语言模型本身只能生成文本。为了让它更有用,其使用工具的能力依赖于一种称为函数调用的机制。

优势:程序化工具使用提升功能性与效率

本节概述了函数调用如何发展为程序化工具使用,这一效率上的飞跃最终将 shell 工具交到了智能体手中。

给定用户请求和一组可用函数,模型可以判断应调用某个函数,并返回结构化的 tool_call 响应:

  • 所选择的函数名称

  • 要传递的参数及其值

  • 运行时执行该函数所需的全部信息

随后,运行时调用该函数,捕获结果并将结果发送回模型的上下文中,模型可以在其中决定是调用另一个函数还是生成最终答案。如果在循环中运行该运行时,并将“functions”重命名为“tools”,它现在就是一个完全自主的智能体。

随着智能体的成熟,工具目录成为智能体框架的一部分。MCP 通过标准化智能体发现和连接外部工具、服务、资源和提示的方式,进一步推动了这一理念。

然而,核心模式保持不变。模型仍然需要在其上下文中拥有工具定义才能使用它们,并且需要每个工具的响应才能推理下一步该做什么。两者都需要上下文。

人们看到了智能体的强大能力,开始为它们加载更多工具。很快,瓶颈从智能体能否使用工具转变为智能体的上下文能处理多少工具。

程序化工具使用打破了每次一个工具的循环,利用了模型在代码和 shell 交互方面的训练远多于工具定义这一事实。通过程序化工具使用,模型不再一次一个调用地处理工具定义,每个结果都堆积回其上下文中。相反,程序化工具让模型通过在沙箱化命令行界面(CLI)中按照自己认为合适的方式编写脚本(如 Python、shell 或模型需要的任何方式)来编排整个工作流。它边执行命令边直接处理结果。模型只看到最终输出。

这为更长、更复杂的智能体任务打开了大门。智能体不再需要用自然语言推理每一个小步骤,而是可以将繁琐的中间过程委托给代码,然后带着关键部分返回。

由此带来的效率提升是巨大的。用于工具定义和中间结果的 token 更少,重复模型往返带来的延迟也更低。准确性也更好,因为智能体可以将代码用于代码擅长的部分(循环、过滤、转换、重试和粘合逻辑)。

仅上下文节省就非常显著。比较两种方法下相同的 200,000 token 预算,如下图 2 所示。图中展示的场景是每个 MCP 工具定义都预先加载(上方)与单个 shell 工具按需发现所需内容(下方)的对比。

图 2 显示,一个具有按需发现能力的单一 shell 工具可以回收数十个预先加载工具定义所消耗的上下文。然而,这种方法引入了安全权衡。

风险:程序化工具使用将提示注入武器化

使程序化工具使用强大的同一特性也使其成为提示注入的放大器。

在程序化工具使用将 shell 交给智能体之前,一次成功的注入可以影响智能体说了什么、选择了哪个类型化工具,或者试图通过其响应泄露什么数据。虽然基于文本的注入带来了重大问题,但其影响仍然主要受限于文本输出和开发者暴露的特定工具。

有了 shell,我们仍然担心模型会被说服说出什么,但我们也担心代码在智能体运行时权限级别下能做什么。

如果模型能被说服运行命令,受影响的推理就不再受类型化 schema 的约束。它受其运行所在的托管运行时的权限级别约束,包括:

  • 文件系统

  • 进程空间

  • 网络

  • 沙箱以及从该执行环境可访问的任何凭据

考虑到这一点,我们可以用一家名为 SupportCo 的虚构公司来说明。

测试 Harness

为了说明这一场景,我们创建了一个虚构的运营方 SupportCo,它在 AgentCore Harness 上运行其客户支持智能体。该 harness 读取入站支持工单,通过下游 MCP 服务器查找账户记录,并将答案返回给写信的人。这是一个默认配置部署,包括托管 harness、内置 shell 工具和经过身份验证的下游 MCP 集成。这里的一切都是标准的,没有任何配置错误。

它的内置 shell 工具能把我们带到哪里?

寻找我们的原语

仅使用提示词,我们开始尝试让模型使用 shell 工具并运行我们的侦察命令。它拒绝了,下一次尝试时它再次拒绝。

这些拒绝表明我们应该采取不同的方法。幸运的是,对于这次测试尝试,harness 的配置旋钮让我们可以按每次调用选择模型。

我们这里不需要一个能力强、对齐良好的模型,只需要一个支持工具调用的模型。因此我们选择了一个更宽松的模型,它完全按照我们的要求做了。它看到一个被允许调用的工具,然后调用了它。

然而,探测仍然比我们希望的要困难。我们的提示词与实际运行的内容之间的联系是松散的。下一 token 预测器不太适合精确复现 shell 语法。如果一个转义符消失了,或者一个短横线被重写了,引号就会偏移到刚好足以出错的程度。

因此我们不再直接提示模型携带载荷,而是通过间接提示注入来落地指令。我们给模型一行它不可能弄错的指令:curl 我们的侦察脚本并将其管道传给 python3。

这就是最终奏效的版本。智能体读取了工单,触发了 shell 工具,我们的侦察脚本在 harness 内运行了。

下面的图 3 展示了该原语(即后续攻击所构建的可复用基础模块),其中一段隐藏的 HTML 注释告诉智能体 curl 我们的侦察脚本并将其管道传给 python3。

我是谁?

我们侦察脚本做的第一件事是执行运行时环境发现。

下面的图 4 展示了在 harness 内执行的 whoami 和 id 命令的输出。

令我们惊讶的是,shell 工具——即运行模型决定执行的任何代码的子进程——是以 root 身份运行的。它并不是受限的服务账户或沙箱用户。

Root 访问权限提供了对操作系统环境的完全可见性,因此我们开始查看还有什么在运行。在意识到 harness 并未附带 ps 之后,我们直接从 /proc 读取进程列表。图 5 展示了进程树的结果。

环境并不繁忙,但有一件事引起了我们的好奇:进程标识符(PID)1,python3.10 -m loopy.server。这会是 harness 运行时吗?我们的侦察脚本,PID 40,是它的直接后代。PID 1 启动了 bash(PID 38,即 shell 工具),后者又运行了我们的代码。整个链条由相同的用户标识符(UID)运行,且每个进程都是 root。

如果 PID 1 是 harness 运行时,那么它的内存就是有趣内容所在之处。因此我们检查了它的状态以及是否可以读取它。下面的图 6 展示了结果。

我们看到两侧的 UID 相同,且 /proc/1/mem 可读。loopy 地址空间中的所有内容都对 shell 工具开放。

在实践中读取它比 cat 要稍微复杂一些。/proc 文件系统(procfs)是内核管理的、通往每个进程运行时状态的窗口,通过许多小型接口暴露,例如:

  • /proc/1/mem 用于原始内存

  • /proc/1/maps 用于内存布局

  • */proc/1/status 用于身份和权限

内存区域布局是稀疏的,因此直接遍历 /proc/1/mem 会碰到未映射的空隙,从而引发 I/O 错误。因此我们分两步进行扫描:

  • 读取 /proc/1/maps 以获取地址空间的布局:起始地址 结束地址 权限(读/写/执行) 该处映射的内容(堆、栈、共享库、匿名分配)

这个布局就是我们搜索位置的地图。

  • 对于每个可读区域,从 /proc/1/mem 读取字节:seek() 到该区域的起始地址 read(size) 字节 在该数据块中搜索 loopy 内存中任何感兴趣的内容,例如字节模式、字符串、结构化数据

无论我们在寻找什么,只要它在 loopy 的内存中,这种方法都能将其提取出来。

我在哪里?

进程树给我们留下了线索。--library-path 将整个运行时指向了 /opt/amazon,因此我们进入了 harness 的 Python 包所在的文件系统,位于 /opt/amazon/lib/python3.10/ 下。下面的图 7 显示了结果。

PID 1 运行了上面图 7 中所示的 loopy/ 子目录。该目录中存在 server.py 证实了我们的 harness 运行时。在与 loopy/ 相同的目录中,我们发现了 bedrock_agentcore/,其中包含 identity/、memory/、services/ 以及一些可供探索的其他 AgentCore 子模块。

凭借对 /proc/1/mem 的读取权限以及触手可及的 bedrock_agentcore 包,有一个模块尤为突出:identity。

有了 root 权限、可读的堆、内部运行的代码以及网络出口,我们唯独缺少一个目标。identity 模块就是目标。要了解原因,让我们更深入地看看 AgentCore Identity 保险库。

AgentCore Identity 保险库

Identity vault 中的每个凭据在静态存储和传输过程中都经过加密,并被封装在 KMS 密钥和访问控制之后。它并非将 Bearer token 放在 Authorization 头中,而是存储在 Identity vault 中,并通过 Amazon Resource Name (ARN) 进行引用,如下图 8 所示。

从理论上讲,这是存储凭据的正确位置。但在运行时会发生什么?

为了让 harness 使用存储在该 vault 中的凭据进行身份验证,首先需要将 ARN 解析为真实的明文密钥。该解析必须在运行时、在其进程内部进行。在本例中,该进程是 PID 1,而我们已经可以读取其内存。

考虑到这一点,我们着手探究 AgentCore Identity ARN 是否以及在哪里会在 harness 内部被解析为真实的 JSON Web Token (JWT)。

窃取 AgentCore Identity JWT

搭建环境

为了了解 AgentCore Identity 在实际中的工作方式,我们搭建了一个简单的场景。我们的测试装置模拟了一个 MCP 服务器,该服务器需要一个 Amazon Cognito Bearer token,并且可以访问个人身份信息 (PII),例如姓名、电话号码或社会安全号码 (SSN) 的后四位。该 token 存储在 vault 中,并且 harness 被配置为在其 Authorization 头中通过 ${arn:...} 引用它,完全按照 AgentCore 文档所述。

图 9 展示了实际的 create_harness 调用,其中 Authorization 头中引用了 Identity vault。

该配置中的内置 shell 工具很容易被忽视,因为它是默认开启的。除非 allowedTools 参数另有说明,否则 AgentCore Harness 会为每个会话提供内置的 shell 和 file_operations 工具,并且两者都以与 PID 1 相同的 UID 运行。

这意味着我们即将介绍的凭据窃取链在默认配置下即可触达。即使操作员发现了 allowedTools,该参数也仅在 InvokeHarness 时限定工具选择,而不是在 CreateHarness 时。如果你了解它,它很灵活;如果你不了解,就很容易被忽视。

窃取过程

在 harness 运行后,我们编写了一个小脚本 pid1_identity_recon_exfil.py。它会在堆中扫描两种模式:

  • JWT 形式的凭证本身

  • 我们需要用于重放该凭证的 MCP 服务器 URL

图 10 展示了该脚本中的模式。

为了让脚本在 harness 中运行,我们复用了之前的原语,如下图 11 所示。它使用了与之前相同的支持工单,但这次的 payload 是我们的 pid1_identity_recon_exfil.py 文件。

图 12 展示了此操作的结果。

一个 JWT(1,034 字节)和 MCP 服务器 URL(重放目标)通过单个 HTTP POST 请求一起发送到我们模拟攻击者的 webhook。

图 13 展示了攻击者端收到的内容。此图显示了在 webhook[.]site 捕获的 HTTP POST 请求和响应,其中携带了 Bearer JWT 和 MCP 重放 URL。这是在智能体总结了之前图 11 中所示的支持工单后不久,到达我们模拟攻击者端点的。

重放:从 Webhook 到 PII

拿到 JWT 和 URL 后,我们从 webhook 中获取了它们并连接到 MCP 服务器。我们能够从自己的笔记本电脑上完成此操作,无需任何 AWS 凭证。下图 14 展示了重放会话的截图。

我们模拟的攻击者列出了 MCP 工具,调用了返回客户 PII 的 lookup_customer 工具,并创建了一个工单。所有这些都来自存储在 AgentCore Identity 保险库中的凭证,该凭证仅通过 ARN 引用,从未被任何用户在本地持有。现在它已落入攻击者手中,可以从互联网上的任何地方完全重放。

我们泄露了谁的 JWT?

我们将泄露的令牌粘贴到 JWT Debugger 中进行解码,其 payload 声明揭示了背后的账户。图 15 展示了解码后的令牌数据,其中包括该账户的用户名:mcp-service。

为什么是操作员的服务账户?

要让执行框架使用来自保管库的 JWT,该 JWT 首先必须存在于保管库中。

最终用户会话令牌不符合条件。它们在登录时新生成,很快过期,并且属于当前登录的任意用户。你无法预先注册它们,也无法为每个用户预置一个新的执行框架来嵌入其令牌。

还有一个权限范围的问题。用户的会话 JWT 授权他们调用 bedrock-agentcore:InvokeHarness,以及其他权限。存储在 AgentCore Identity 保管库中的凭证则完全不同。它是供执行框架的执行角色用于向下游服务进行身份验证的,在我们的场景中是客户端的 MCP 服务器。这是用户从未拥有、也本不应拥有的权限。这是执行框架代表操作者而非调用者行事。

图 16 展示了权限边界的两侧:

  • 调用者仅被允许调用 InvokeHarness

  • 执行框架的执行角色被允许访问操作者接入的每一个下游服务

调用者只能向执行框架请求帮助。然而,一旦被调用,执行框架就可以访问操作者接入的每一个下游服务,包括凭证。

保管库用于存放稳定的凭证,包括操作者的服务账户,在 create_harness 时一次性接入。这就是我们在本文上一节开头设置的那个,让我们窃取一个 AgentCore Identity JWT。随后它会在每个用户会话中重复使用,这就是最终落入 PID 1 堆内存并被窃取的凭证。被窃取的凭证不是最终用户的 JWT,而是 mcp-service,即操作者的服务账户。

披露时间线

  • 年 5 月 19 日:通过 HackerOne 报告给 AWS 安全团队(报告编号 #3747844)

  • 年 6 月 8 日:AWS 安全团队回复,要求复现并就范围进行澄清

  • 年 6 月 10 日:确认此发现与早先的报告(#3737800)具有相同的根本原因,两份报告被合并

  • 年 6 月 10 日:AWS 根据 AgentCore 责任共担模型,以 allowedTools 范围限定和出口过滤属于客户侧控制措施为由,将该报告作为信息性报告关闭

结论

随着 AI 智能体的推理能力变得更敏锐、运行时间更长且更加自主,执行框架需要控制住的攻击面会随着它赋予智能体的每一项能力而扩大。我们的研究端到端地梳理了这种攻击面扩大的一种形式。这包括一个 shell 工具运行在执行框架解析其凭证的同一内存空间中,以及到 shell 工具能够访问时,保管库交出的每一个凭证都以明文形式存在于堆内存中。

保管库成功保护了静态和传输中的凭证,但 shell 工具的内存访问绕过了这些保护。

我们的发现凸显了托管智能体运行时面临的一个更广泛的挑战:

  • 如果未正确限定范围,shell 工具可能成为新的边界。通用 shell 之所以强大,是因为它可以触及运行时所能触及的任何东西。将其范围缩小以防止数据外泄,同时也会剥夺它使程序化工具使用值得采用的灵活性。而且模型的推理无法可靠地区分合法指令和注入指令,因此限制攻击者行为的是 shell 工具的可触及范围,而非模型的判断力。shell 工具能触及的任何东西(文件系统、网络、进程内存、下游服务)就是注入所能触及的东西。

  • 保险库保护静态和传输中的数据,但不保护使用中的数据。harness 在运行时解析的任何凭据都必须变为明文才能使用。使用中的保护是一个独立的问题,保险库无法解决。

  • 考虑你的 harness 代表哪些凭据行事。Harness 可能需要长期、高权限的凭据来完成其下游工作并保持自主性。无论调用用户自身的权限范围如何,它们解析的任何凭据都会通过任何成功的注入变得可触及。

我们建议使用 AgentCore Harness 的组织确保覆盖以下方面:

  • 在 InvokeHarness 时(而非 CreateHarness 时)将 allowedTools 参数限定为每个会话所需的范围。内置的 shell 和 file_operations 工具默认启用。不需要它们的会话不应获得它们。

  • 将每个 Identity 保险库服务账号限定为其下游集成的最小权限。泄露的凭据价值取决于其权限范围所能换取的东西。

  • 监控 harness 容器的出站流量。任何不在你下游集成列表中的端点都是活跃注入的证据,而非配置漂移。

如果你正在构建托管智能体运行时,请将 harness 赋予模型的每一项能力视为攻击面原语,而非附加的生产力功能。运行时解析的任何凭据都必须存放在 shell 工具无法读取的地方,或者 shell 工具必须运行在与解析该凭据的进程隔离的沙箱中。没有这些隔离边界,运行时凭据将始终暴露于 shell 工具。

Palo Alto Networks 的防护与缓解措施

Palo Alto Networks 的客户通过以下产品可以更好地防御上述威胁:

  • Cortex Cloud 通过将静态权限基线与深度行为上下文相结合,帮助保护云态势和运行时操作免受身份驱动的威胁。通过将本研究中讨论的功能身份基线嵌入到我们针对云 VM 计算和无服务器智能体的检测引擎中,Cortex Cloud 增加了一层关键的运营上下文,使安全团队能够过滤掉嘈杂的误报,并果断捕获试图在环境中伪装、篡改配置或执行异常操作的威胁行为者。

Unit 42 云安全评估是一项评估服务,审查云基础设施以识别错误配置和安全缺口。

如果你认为你可能已遭到入侵或有紧急事项,请联系 Unit 42 事件响应团队或致电:

  • 北美:免费电话:+1 (866) 486-4842 (866.4.UNIT42)

  • 英国:+44.20.3743.3660

  • 欧洲和中东:+31.20.299.3130

  • 亚洲:+65.6983.8730

  • 日本:+81.50.1790.0200

  • 澳大利亚:+61.2.4062.7950

  • 印度:000 800 050 45107

  • 韩国:+82.080.467.8774

Palo Alto Networks 已与我们的 Cyber Threat Alliance (CTA) 成员分享了这些发现。CTA 成员利用这些情报快速向其客户部署防护措施,并系统性地瓦解恶意网络行为者。了解更多关于 Cyber Threat Alliance 的信息。



转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:Palo Alto Unit42

原创地址:https://unit42.paloaltonetworks.com/securing-aws-agentcore-harness-credentials/

原文作者:Niv Rabin;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-11-21

  • 博文量
    1090
  • 访问量
    546977