AutoJack:一个网页如何远程控制运行你AI智能体的主机"

admin 2026-10-24 03:46:45 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

AutoJack:一个网页如何远程控制运行你 AI 智能体的主机

幻泉之洲

2026年6月19日 13:50
北京

在小说阅读器读本章

去阅读

安全研究人员在 AutoGen Studio 里发现了一条完整的利用链:恶意网页通过被浏览的智能体绕过本地信任边界,直连未鉴权的 MCP WebSocket,最终在开发者主机上执行任意命令。这条链子不依赖任何用户点击,只要智能体打开了攻击者的页面就够了。文章拆解了链条上三个独立缺陷,给出了具体的修复和防护建议,也讨论了这类模式对整个智能体生态意味着什么。

为什么要盯着智能体框架

现在的 AI 智能体早不是简单的文本生成器了。它们读文件、浏览网页、调 API、往系统里派命令。这些能力让智能体变得有用,也正是这些能力让我们想搞清楚:把模型跟工具连起来的框架里,到底埋着多少系统级的执行风险。之前我们聊过 Microsoft Semantic Kernel 里的 RCE 原语[1],这次我们把视角往上抬一层,看向开发基础设施和原型界面。你会发现,那些让实验变得顺手的能力,在没有防护的原型环境里,完全能变成远程代码执行的投递通道。

重点不是别碰原型。重点是:当你核心服务器或笔记本上的智能体既能浏览公网,又能跟本地特权服务打招呼,localhost 就不再是信任边界了。做防御的人得为这个做好准备。

AutoGen Studio 是个什么东西

AutoGen Studio[2]是架在 AutoGen[3]上面的一个用户界面,AutoGen 是微软研究院搞的多智能体框架。它让开发者可以组装智能体、挂工具(包括 MCP 服务器),然后快速跑实验。官方的文档说得很明白:这是个研究原型,快速迭代优先,别当生产环境加固版用。

AutoJack 链条速览

下面这条利用链只在演示层面有意义,当前构建版本里已经不存在了。拿出来说是因为防御方需要在其他框架里能认出这个模式。

链条把 AutoGen Studio 的 MCP WebSocket 面上三个互不相关的弱点串了起来:

  • 来源允许列表信任 localhost,但本机智能体本身就是 localhost(CWE-1385,WebSocket 缺少来源验证):MCP WebSocket 只接 Origin 是 http://127.0.0.1 或 http://localhost 的连接。这确实能挡住浏览器直接访问 evil.com。但挡不住同一台机器上 AutoGen 智能体驱动的无头浏览器渲染出来的 JavaScript。
  • 认证中间件对 MCP 路径做了豁免(CWE-306,关键功能缺少身份验证):AutoGen Studio 的认证中间件明确跳过 /api/mcp/\ 和 /api/ws/\,本意是让这些路径自己去做鉴权。可是 MCP WebSocket 处理器完全没补上这步检查。结果就是,不管应用配置了哪种认证模式,MCP WebSocket 都能无凭据连接。
  • 从 URL 里拿到的 server\_params 直接当命令执行(CWE-78,OS 命令中特殊元素过滤不当):端点接收 server\_params 查询参数,base64 解码出一个 JSON 然后反序列化成 StdioServerParams,接着把里面的 command 和 args 喂给 stdio\_client(…)。没有任何白名单,calc.exe、powershell.exe -enc …、bash -c ‘…’ 全都被当成“MCP 服务器”接受了。

把这三样和公网上一个网页串起来,让同一台机器上的 AutoGen 智能体去渲染它,你就拿到了一个远程代码执行的原语。根本不需要用户额外点任何东西,只要把智能体引到攻击页面就够了。

▲ 图 1:端到端利用链。攻击页面由本地浏览智能体渲染;页面打开一个 WebSocket 连到 ws://localhost:8081/api/mcp/ws/?server\_params=;AutoGen Studio 解码载荷,以开发者账户权限启动攻击者选择的命令。

我们把这套手法叫作 AutoJack:攻击者“劫持”了浏览智能体,把它当成被误导的中间人,开车跨过 localhost 边界,一头扎进 AutoGen Studio 的 MCP 控制面里。

链条解剖

问题 1:来源白名单被智能体自己破了

AutoGen Studio 的 MCP WebSocket 依赖一种很常规的防御手段来防浏览器驱动的跨站 WebSocket 劫持(CSWSH):只放行来自 127.0.0.1 / localhost 的同源连接。

allowed\_origins = [“http://127.0.0.1”, “http://localhost”]

对真人用户来说,这个控制没毛病。他打开个标签页访问 evil.com,浏览器会把 Origin 头设成 hxxps://evil[.]com,检查不通过,连接拒绝。

可换成智能体就不一样了。一个 AutoGen 智能体如果装上了内置的网页浏览工具,比如 MultimodalWebSurfer、fetch\_webpage\_tool,或者任何一种基于 Playwright 的冲浪工具,甚至能跑代码的工具来发起请求或 WebSocket,它就是工作站上的一个进程。它加载的任何东西都天然带着 localhost 身份。无头浏览器里执行的 JavaScript,其来源就是智能体导航过去的那个地址,它发出的 WebSocket 调用携带的 Origin 恰好满足白名单要求。

▲ 图 2:通过智能体绕过来源检查。AutoJack —— 开发者工作站上的浏览智能体被外部内容引导,连接到 localhost 上的 AutoGen Studio MCP 控制面,消解了环回信任边界。

问题 2:认证中间件直接放过了 MCP

AutoGen Studio 支持好几种认证模式(none、github、msal、firebase)。它们全挂在一个统一中间件 AuthMiddleware 上,运行在 FastAPI 路由分发之前。在 PyPI 上的版本里,这个中间件对 WebSocket 风格的路径做了提前返回:

auth excluded for these paths; they were intended to do their own checks

if request.url.path.startswith(\"/api/ws\") or request.url.path.startswith(\"/api/mcp\"):
   return await call\_next(request)

意图能理解:ASGI 中间件没法像拦住 HTTP 请求那样有效控制 WebSocket 握手,所以设计上要求 WebSocket 处理器自己在 accept 时做认证。MCP 那条路由没接过这个责任。结果就是这个发布包里,下面的表格成立:

认证配置 REST API 受保护? /api/mcp/ws/\* 受保护?
type: none 否 否
type: github 是 否
type: msal 是 否
type: firebase 是 否

在 config.yaml 里开启认证,这洞自己不会堵上。

问题 3:URL 里的 server\_params 就是命令行

开发分支的 MCP WebSocket 路由会读 server\_params 查询参数,base64 解码,JSON 解析成 StdioServerParams,然后直接塞进 stdio\_client(…):

@router.websocket(\"/ws/{session\_id}\")
async def mcp\_websocket(websocket: WebSocket, session\_id: str):
   encoded = websocket.query\_params.get(\"server\_params\")
   decoded = base64.b64decode(encoded)
   params = StdioServerParams(\\json.loads(decoded))
   await create\_mcp\_session(bridge, params, session\_id)

StdioServerParams.command 和 StdioServerParams.args 被直接传给 stdio\_client,后者用它来启动“MCP 服务器”进程。完全没检查可执行文件是不是真的能讲 MCP 协议,所以同样这套流程,calc.exe、powershell.exe -enc …、bash -c ‘…’ 全都能跑。

一个最小化的载荷长这样:

{
 \"type\": \"StdioServerParams\",
 \"command\": \"calc.exe\",
 \"args\": [],
 \"env\": { \"pwned\": \"true\" }
}

base64 编码后拼进查询串,完整性请求就变成:

ws://localhost:8081/api/mcp/ws/?server\_params=

结合问题 1 和问题 2,攻击者唯一需要的就是让智能体渲染一个包含这个 URL 的页面。

把它们串起来:一个现实场景

为了验证端到端链条,我们写了两个小东西:

malicious\_web\_server.py:一个架在 http://attacker[.]example/websocket-interactive 的网页。页面里唯一有意义的内容是一个脚本,去打开上面那个 WebSocket,附上跑 calc.exe 的 base64 载荷。

web\_summarizer\_app.py:一个“网页内容摘要器” AutoGen 智能体,包在一个 Flask UI 里。应用从用户那里收一个 URL,交给 MultimodalWebSurfer 智能体,附上提示“浏览这个 URL 并总结内容”。换句话说,这就是任何一个基于框架能搭出来的完整 AutoGen 智能体,Flask 页面只是接口。

完整流程是这样的:

  1. 开发者构建了一个 AutoGen 智能体,比如“网页摘要器”,或者任何带了浏览能力的智能体,跑在和 AutoGen Studio 同一台机器上。
  2. 攻击者在某个正经新闻站点的评论区埋一条恶意链接,或者用户要求摘要器智能体去总结一个攻击者控制的 URL。这可以通过直接提示词、前面内容里的提示注入,或者应用里的 URL 输入框触发。
  3. 智能体的浏览工具(我们的例子里是 MultimodalWebSurfer)驱动无头浏览器导航到攻击页面。
  4. 页面里的 JavaScript 打开 ws://localhost:8081/api/mcp/ws/?server\_params=。因为浏览器就在本机,Origin 合格;因为认证中间件直接短路了 /api/mcp/\*,不需要凭据。
  5. AutoGen Studio 解码载荷,以开发者账户权限启动 calc.exe(或者你指定的任何东西)。

我们把这个演示做成可控的本地概念验证。下文截图展示了一条完整的单机链条:开发者在本机 8081 端口(默认端口)启动 AutoGen Studio,打开“网页内容摘要器”应用,提交一个攻击者控制的 URL。MultimodalWebSurfer 渲染页面后几秒,开发者桌面弹出 calc.exe,启动它的进程是 AutoGen Studio,而不是浏览器,也不是智能体的无头 Chromium。

▲ 我们构建的 AutoGen 浏览器智能体按设计抓取并总结了网站内容。

▲ AutoJack 实战:浏览智能体渲染攻击页面;页面的 JavaScript 打开一个 WebSocket 连到 ws://localhost:8081/api/mcp/ws/…?server\_params=;AutoGen Studio 解码载荷并启动 calc.exe。在真实部署中,同样的原语可以执行攻击者选择的其他命令,权限取决于运行 AutoGen Studio 的那个进程。


参考资料

[1] https://www.microsoft.com/en-us/security/blog/2026/05/07/prompts-become-shells-rce-vulnerabilities-ai-agent-frameworks/

[2] https://microsoft.github.io/autogen/docs/autogen-studio/getting-started

[3] https://microsoft.github.io/autogen/

[4] https://github.com/microsoft/autogen/commit/b0477309d2a0baf489aa256646e41e513ab3bfe8

[5] https://aka.ms/threatintelblog

[6] https://www.linkedin.com/showcase/microsoft-threat-intelligence

[7] https://bsky.app/profile/threatintel.microsoft.com

[8] https://thecyberwire.com/podcasts/microsoft-threat-intelligence

[9] https://learn.microsoft.com/en-us/microsoft-365-copilot/extensibility/copilot-studio-agent-builder

[10] https://learn.microsoft.com/en-us/copilot/microsoft-365/microsoft-365-copilot-ai-security

[11] https://www.microsoft.com/en-us/security/blog/2024/04/11/how-microsoft-discovers-and-mitigates-evolving-attacks-against-ai-guardrails/

[12] https://learn.microsoft.com/en-us/defender-cloud-apps/ai-agent-protection

[13] https://microsoft.github.io/zerotrustassessment/

[14] https://www.microsoft.com/en-us/security/blog/2026/06/18/autojack-single-page-rce-host-running-ai-agent/


AutoJack:一个网页如何远程控制运行你AI智能体的主机" 网络安全文章

AutoJack:一个网页如何远程控制运行你AI智能体的主机"

文章披露AutoGenStudio框架中的AutoJack漏洞利用链,恶意网页可通过浏览智能体绕过localhost信任边界,直连未鉴权的MCPWebSocket服务,在主机上执行任意命令。攻击无需用户交互,仅需诱导智能体访问恶意页面。漏洞涉及来源验证缺失、认证中间件豁免路径、命令注入三重缺陷。建议加强本地服务鉴权、严格验证WebSocket来源、对MCP参数实施白名单过滤。
千字解析实习垂直性,如何在校招当一名受欢迎的应届生(网络安全)" 网络安全文章

千字解析实习垂直性,如何在校招当一名受欢迎的应届生(网络安全)"

本文针对网络安全校招,重点分析实习垂直性的价值与实现路径。指出垂直实习能体现职业规划能力、降低企业培养成本,并从业务场景、技能要求、公司业务三个维度定义垂直性。建议通过渗透测试、工具开发等递进式实习积累经验,强调大一尽早开始刷3段垂直实习可成为校招优势候选人。
第六章 - 重生之我是AI人:47个攻击技能—怎么被LLM调用" 网络安全文章

第六章 - 重生之我是AI人:47个攻击技能—怎么被LLM调用"

文档介绍Hati系统如何利用Markdown文件定义47个渗透测试技能,通过SkillLoader自动加载匹配目标信息,并由LLM动态适配具体攻击模板。关键创新包括:基于关键词的快速技能匹配机制、LLM将通用技能模板转化为针对目标的实际HTTP请求、多模式确认机制将误报率从25%降至3%。系统支持零代码添加新技能,只需编写Markdown文件即可扩展能力。
记录某系统实战内网K8S渗透" 网络安全文章

记录某系统实战内网K8S渗透"

本文记录了一次针对Spring框架系统的完整内网渗透实战过程。攻击者通过heapdump信息泄露获取Shiro密钥,利用反序列化漏洞获得初始权限后进入内网,发现K8S集群2379和6443端口未授权访问,通过etcd获取ServiceAccountToken后成功控制容器环境,最终在100多个集群中实现权限提升。文章提供了具体操作命令并强调需合法授权。
评论:0   参与:  0