尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Envoy MCP JSON REST Bridge 路径穿越漏洞修复解析:模板变量如何被安全地注入上游 :path

Envoy MCP JSON REST Bridge 路径穿越漏洞修复解析:模板变量如何被安全地注入上游 :path Envoy MCP JSON REST Bridge 路径穿越漏洞修复解析模板变量如何被安全地注入上游 :path【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本篇技术指南聚焦 Envoy 中mcp_json_rest_bridgeMCP JSON REST BridgeHTTP 过滤器的一次安全修复路径模板变量path-template variable的值来自攻击者可控的tools/call参数过去会被原样verbatim拼入上游请求的:path导致../../admin/secrets这类值可形成路径穿越path traversal。文章将结合 changelogs/current/bug_fixes/mcp_json_rest_bridge__prevent-path-traversal-via-simple-template-variables.rst、http_request_builder.cc 源码与对应测试剖析漏洞成因、双层修复策略拒绝穿越段 简单变量百分号编码/、异常/统计标记体系以及如何配置与验证该行为。读完你将掌握MCP→REST 转码中 URL 路径模板的替换原理、攻击面所在、修复边界通配变量为何仍可跨段以及对应的回归测试用例。一、背景MCP JSON REST Bridge 是什么mcp_json_rest_bridge是 Envoy 的一个 HTTP 过滤器扩展扩展名envoy.filters.http.mcp_json_rest_bridge其职责是把 Model Context ProtocolMCP的 JSON-RPC 请求转码为标准 JSON-REST HTTP 请求从而让现有 REST 后端无需原生支持 MCP 即可充当 MCP 服务器。其核心机制见 mcp_json_rest_bridge.proto转码Transcoding将 JSON-RPC 请求负载转换为 HTTP REST 请求再把 JSON 响应映射回 JSON-RPC会话协商Session negotiation处理 MCP 连接建立阶段的前置握手initialize/notifications/initialized工具调用映射将tools/call请求按HttpRule规范转换为真实 HTTP 请求对应实现见 mcp_json_rest_bridge_filter.cc 中的handleMcpMethod与 http_request_builder.cc 中的buildHttpRequest。在tools/call转码过程中HttpRule的路径模板例如get: /v1/projects/{project_id}/resources/{resource_id}会被arguments中的同名参数替换。漏洞正是发生在这个把参数值替换进 URL的环节——如果替换值未经净化就进入上游:path攻击者就可以通过构造的arguments把请求导向任意路径例如把{id}替换为../../admin/secrets。二、漏洞根因模板变量原样注入上游 :path2.1 模板替换语义HttpRule的路径模板用花括号{}标记可替换段变量名必须对应 JSON-RPCarguments中的字段支持点号访问嵌套字段如user.id。buildHttpRequest会用正则\{([a-zA-Z0-9_.])(?:.*?)?\}从模板中提取所有模板变量见 http_request_builder.cc随后对每个变量执行替换。修复前的行为是arguments中取出的原始字符串被直接替换进 URLsubstitutePathTemplateVariable原样url.replace(...)随后该 URL 被设置为上游请求的:path。2.2 为什么这是可利用的攻击面从源码注释http_request_builder.cc可以确认两点关键事实构造出的 URL 被原样安装为上游:path且 Envoy 不会对其重新做路径规范化因此只要某个模板变量的值里含有.或..段上游或上游再做解码/折叠的中间层就会把/v1/users/../../admin/secrets/profile这类路径解析为/admin/secrets/profile实现穿越。tools/call的arguments完全由 MCP 客户端提供而 MCP 服务器端点通常暴露给 LLM Agent 调用Agent 的输入又可能被提示词注入prompt injection等手法诱导——这正是该漏洞被视为攻击者可控attacker-controlled的原因。2.3 修复前的典型危害示例假设工具配置为tools: { name: getUser http_rule: { get: /v1/users/{id}/profile } }若客户端发送如下tools/call{ jsonrpc: 2.0, id: 123, method: tools/call, params: { name: getUser, arguments: { id: ../../admin/secrets } } }修复前会得到上游路径/v1/users/../../admin/secrets/profile从而访问到本应不可达的/admin/secrets/profile。对应回归测试 http_request_builder_test.cc 明确记录了这一点Before the fix this returned/v1/users/../../admin/secrets/profile。三、修复方案双层防御本次修复对应 changelog mcp_json_rest_bridge__prevent-path-traversal-via-simple-template-variables.rst在constructBaseUrl中实现了两层防御逻辑集中在 http_request_builder.cc。3.1 第一层拒绝所有模板变量中的穿越段对每一个模板变量替换前先按/与\切分取值for (const absl::string_view segment : absl::StrSplit(raw_value, absl::ByAnyChar(\\/))) { if (segment . || segment ..) { bridge_status BridgeStatus::RequestToolsCallPathTraversalRejected; return absl::InvalidArgumentError(absl::StrCat( path template variable , element, must not contain path traversal segments)); } }要点覆盖所有变量类型无论是简单变量{id}还是带显式模式的通配变量{nameprojects/*}只要值中出现独立的.或..段即被拒绝。这是纵深防御defense-in-depth——通配变量的值同样来自攻击者可控的arguments修复前它也能产生/v1/../../admin/secrets/shelves这类路径见 http_request_builder_test.cc\也被视为段分隔符虽然反斜杠最终会被百分号编码为%5C但若上游先解码再把它折叠为/仍可能构成穿越因此校验阶段就把\与/同等对待见 http_request_builder_test.cc非穿越段的反斜杠仍允许只是被百分号编码保证合法输入不受影响a\b→a%5Cb见 http_request_builder_test.cc。3.2 第二层简单变量将/百分号编码限制在单一路径段修复在 http_request_builder.h 中定义了两组保留字符集// 用于 query 参数与带显式模式的通配变量 inline constexpr absl::string_view ReservedChars R( !#$%()*,:;?[\]^{|}~); // 简单变量专用额外把 / 也编码将变量限制在单个路径段内 inline constexpr absl::string_view ReservedCharsWithSlash R( !#$%()*,/:;?[\]^{|}~);在constructBaseUrl中按变量类型选择字符集const absl::string_view reserved_chars absl::StrContains(pattern, absl::StrCat({, element, )) ? ReservedChars : ReservedCharsWithSlash; const std::string value_str Http::Utility::PercentEncoding::encode(raw_value, reserved_chars);即简单变量{id}无pattern/会被编码为%2F从而被限制在单个路径段内无法通过额外斜杠改变路由前缀。测试用例{id: a/b}得到/v1/users/a%2Fb/profile见 http_request_builder_test.cc带显式模式的变量{nameprojects/*}语义上允许跨段这是 Google API path template 的合法用法如projects/123456789因此其/被保留交由运维人员显式声明——这是修复刻意保留的能力边界。测试{parent: projects/123456789}得到/v1/projects/123456789/shelves见 http_request_builder_test.cc。3.3 两层的分工简单说拒绝检查保证任何变量值都造不出..穿越段编码规则保证简单变量连跨段都做不到。前者是硬性拦截后者是纵深约束——即便值中不含独立..段简单变量的斜杠也无法逃逸出所属路径段从而兼顾了路径路由语义不被绕过与Google API path template 的通配语法不受影响。四、被拒绝后的响应与可观测性4.1 JSON-RPC 错误响应当穿越被拒绝时过滤器不会把请求发往上游而是直接以本地响应local reply返回 JSON-RPC 错误。完整的端到端行为见测试 mcp_json_rest_bridge_filter_test.cc请求arguments.parent projects/../secrets被拦截返回 HTTP 200 JSON-RPC 错误负载{code:-32602,message:path template variable parent must not contain path traversal segments}响应包装为完整 JSON-RPC 错误信封{error:{code:-32602,message:...},id:123,jsonrpc:2.0}错误码-32602对应 JSON-RPC 规范中的 Invalid params与 MCP 请求参数不合法语义吻合。4.2 状态标记与动态元数据被拒绝时设置BridgeStatus::RequestToolsCallPathTraversalRejected对应统计/状态字符串为mcp_json_rest_bridge_request_tools_call_path_traversal_rejected见 bridge_status.h 与BridgeStatusValues定义。当request_storage_mode: DYNAMIC_METADATA时该状态还会写入 dynamic metadata命名空间为过滤器配置名如envoy.filters.http.mcp_json_rest_bridge测试中可见元数据形如{ status: mcp_json_rest_bridge_request_tools_call_path_traversal_rejected, method: tools/call, params: { ... } }这意味着运维人员可以基于该状态进行告警、审计或按路径/元数据做后续策略。五、如何配置与验证5.1 相关配置项速览修复不引入任何新配置项行为默认开启。与此安全边界相关的既有配置见 mcp_json_rest_bridge.proto配置字段作用默认值max_request_body_size请求体缓冲上限超限返回 41364KB65536 字节0 表示禁用max_response_body_size响应体缓冲上限超限返回错误1MB1048576 字节0 表示禁用request_storage_modeMCP 请求属性是否写入动态元数据不存储DYNAMIC_METADATA可开启disable_clear_route_cache转码后是否清空路由缓存以重新选路false默认清空per_route_only是否仅在存在 per-route 配置时才生效falsetool_config.tools[].http_rule工具到 HTTP 方法的映射规则路径模板所在无tool_config.default_server_info工具默认端点host/path缺省回退/mcp无一个使用简单变量与通配变量的典型工具配置示例tool_config: default_server_info: path: /mcp tools: - name: getUser http_rule: get: /v1/users/{id}/profile - name: listProjects http_rule: get: /v1/{parentprojects/*}/shelves在上述配置下getUser的{id}是简单变量——/会被编码、..会被拒绝listProjects的{parentprojects/*}是通配变量——允许跨段但同样拒绝..段。5.2 验证方式单元测试test/extensions/filters/http/mcp_json_rest_bridge/http_request_builder_test.cc直接验证constructBaseUrl的替换与拦截行为简单变量拒绝穿越、编码/、放行单段、通配保留/、通配拒绝穿越、反斜杠穿越拒绝、非穿越反斜杠编码过滤器测试test/extensions/filters/http/mcp_json_rest_bridge/mcp_json_rest_bridge_filter_test.cc验证从tools/call请求到本地 JSON-RPC 错误响应的完整链路以及 dynamic metadata 的写入手工验证向配置了mcp_json_rest_bridge的监听端口发送带恶意arguments的tools/call如{id:../../etc/passwd}观察返回的-32602错误与mcp_json_rest_bridge_request_tools_call_path_traversal_rejected状态同时验证合法单段值如alice与通配跨段值如projects/123仍正常工作。六、安全边界与注意事项通配变量是刻意的例外{nameprojects/*}允许跨段是 Google API path template 的合法语义由运维显式声明但其值同样受..段拒绝约束只是/不被编码。配置通配模板时应意识到该变量的值仍可影响路由前缀之后的具体路径需确保匹配模式本身收窄了可访问范围上游行为不可假设修复针对的是构造 URL 原样进入:path、Envoy 不再规范化的现实同时防御了上游解码后折叠\→/的情况。对于还可能在更外层做重写/解码的部署仍建议遵循最小权限原则暴露工具请求体大小限制是配套防线max_request_body_size默认 64KB、max_response_body_size默认 1MB防止转码缓冲被恶意大负载打满生产环境不建议置 0 禁用行为默认开启、无版本开关该修复直接随过滤器行为生效升级后即覆盖所有使用该过滤器的配置无需额外配置项配合。七、总结本次修复从攻击面出发针对 MCP JSON REST Bridge 将工具参数注入上游:path的转码环节建立了逐变量拒绝./..段 简单变量编码/限单段的双层防线并以 JSON-RPC-32602错误、mcp_json_rest_bridge_request_tools_call_path_traversal_rejected状态与动态元数据提供清晰的失败反馈。对使用者而言理解{id}与{namepattern}在编码策略上的差异是安全配置该过滤器、防止 LLM Agent 输入被利用的关键前提。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表