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 页面只是接口。
完整流程是这样的:
- 开发者构建了一个 AutoGen 智能体,比如“网页摘要器”,或者任何带了浏览能力的智能体,跑在和 AutoGen Studio 同一台机器上。
- 攻击者在某个正经新闻站点的评论区埋一条恶意链接,或者用户要求摘要器智能体去总结一个攻击者控制的 URL。这可以通过直接提示词、前面内容里的提示注入,或者应用里的 URL 输入框触发。
- 智能体的浏览工具(我们的例子里是 MultimodalWebSurfer)驱动无头浏览器导航到攻击页面。
- 页面里的 JavaScript 打开 ws://localhost:8081/api/mcp/ws/?server\_params=。因为浏览器就在本机,Origin 合格;因为认证中间件直接短路了 /api/mcp/\*,不需要凭据。
- 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/
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论