点开一条 ChatGPT 分享链接,私聊就被端了:数学键盘 + YouTube JSONP 组成的 P1 漏洞链

TL;DR

安全公司 Parameter Labs 在 ChatGPT 上发现并演示了一条完整的账号接管链:攻击者制作一个普通的公开分享会话,受害者点开链接,攻击者的 JavaScript 就以 chatgpt.com 的身份跑在受害者登录会话里------可以枚举其全部会话、读取从未分享过的私聊内容、把数据外传到任意服务器。不需要装 App、不需要加工作区、不需要贴代码,唯一动作就是打开链接。OpenAI 10 月 18 日收到报告,21 日复现并把等级从 P2 升到 P1,26 日完成双前端修复,发放赏金 $5,000。10 月 31 日细节公开后冲上 Hacker News 热榜(297 分 / 145 评论)。

这条链最值得前端工程师细读的地方在于:每一个环节单看都合理,洞只存在于特性的「接缝」里。

攻击效果先摆出来

Parameter 在自己控制的两个账号间做了受控验证。受害者打开恶意分享链接后,注入的代码做了三件事:

  1. 调 GET /backend-api/conversations 枚举受害者最近的会话列表;
  2. 选中一条与攻击者毫无关系、从未分享过 的私聊,调 GET /backend-api/conversations/<id> 拿到完整消息内容;
  3. 用一个普通的图片请求,把响应中的关键字段发到研究者控制的服务器。

这不是「页面上能看到什么就读什么」的抓取------注入代码读的是会话的 access token 和 account ID,带着 Authorization: Bearer 头走认证 API。用作者的话说:以受害者身份对 ChatGPT 能做的任何操作,都在同一个安全边界内。

逐环拆链:五次「差一点就被挡住」

第一环:Preview 沙箱本身没问题

ChatGPT 的 HTML Preview(就是原来的 Canvas/Artifacts 那套)会把会话里的 HTML 代码块渲染成一个小网页。因为里面可能是任意代码,ChatGPT 把它放进独立域名下的受限 iframe 。实测也确实隔离住了:Preview 里读 parent.document 直接被浏览器拦下。

故事本该到此为止。问题是,主页面里还有别的东西愿意「听电话」。

第二环:一个图表,把数学键盘的耳朵装进了主页面

攻击者的会话里放了一个普通的交互图表。这个图表背后加载了数学公式库 MathLive ------加载这个动作顺带在主 ChatGPT 页面 注册了一个 postMessage 监听器,负责处理虚拟键盘相关的消息。

postMessage 是浏览器允许跨 iframe 传消息的正规机制:沙箱里的 Preview 进不了主页面,但可以往信箱里投信。安全前提只有一个------收信方得先看清寄信人是谁。

MathLive 没看清。它的顶层控制器对来源的策略是 none(谁的信都收),也不校验 event.source。其中一条「更新键盘布局」的消息,允许 layout 数据里携带原始 HTML。

于是沙箱里的 Preview 发出两条消息:第一条把虚拟键盘布局替换成攻击者的 HTML,第二条让键盘弹出来。键盘渲染时执行了等价于这样的代码:

js 复制代码
keyboardContainer.innerHTML = MathfieldElement.createHTML(keyboardHTML);

那个 createHTML 看名字像消毒函数,实际只是 Trusted Types 的身份包装------标记「可信」但不清洗内容,攻击者的 HTML 原样通过。

第三环:innerHTML 里的 script 不执行?那就换个文档

到这里拿到了 HTML 注入,但 innerHTML 插进去的 <script> 标签是不会执行的。这是浏览器的老规矩。

解法是 <iframe srcdoc="...">:把 HTML 直接写在 iframe 的属性里,浏览器会为它解析出一个全新的文档 。关键在于------这个 iframe 没带 sandbox 属性,而且是主页面自己创建的,所以新文档继承了 chatgpt.com 的身份,还能反过来访问 parent。JS 执行到手,而且是在受害者的登录上下文里。

第四环:CSP 拦住了?YouTube 替你把脚本送进来

ChatGPT 的内容安全策略(CSP)会拦截内联脚本。但它允许从 www.youtube.com 加载脚本。

YouTube 的 oEmbed 端点支持 JSONP 风格的 callback 参数------响应本身就是 JavaScript。更有意思的是它的校验顺序:先把 callback 拼进响应,再检查名字合法性。于是这个请求:

ini 复制代码
https://www.youtube.com/oembed?callback=globalThis.__payload=...;void

返回的响应开头是:

js 复制代码
// API callback
globalThis.__payload=...;void({
  "error": { "code": 400, "message": "Invalid JSONP callback name: ..." }
});

结尾的 ;void 把 YouTube 追加的错误对象整个吞掉,语法完全合法。CSP 允许 YouTube,浏览器就把这份响应当脚本加载执行------任意代码,借道大牌域名,穿过 CSP。

需要说明:作者明确指出 YouTube JSONP 只是最后一跳,不是根因。就算封了这个端点,「不可信 Preview 能往主页面注 HTML」的病根还在,换个跳板还能来。

第五环:从「实验室玩具」到「一条链接」

最初的版本需要受害者先连接一个攻击者的 App 才能触发------不像真实攻击。真正的突破是把两个组件塞进同一条普通公开分享会话:

  1. 一个真实的图表(负责在主页面装上 MathLive 监听器);
  2. 一块后续的 HTML 代码块(Preview 发出那两条消息)。

/share/<id> 链接会把整条链原样带给任何打开它的人。早期版本需要受害者手动点一次 Preview 按钮;后来的版本把 HTML 块标记为「可预览」,点开链接即自动触发(约 4.5 秒后弹窗),硬刷新后依然复现。图表和 Preview 各自独立加载存在竞态,最终载荷靠限时重发消息兜底。

OpenAI 的修复与时间线

日期 事件
10-13 对生产代码确认 MathLive 消息→HTML 路径
10-14 正常 UI 全链复现,升级为任意 JS 执行
10-16 跨账号确认公开分享交付
10-17 确认「点开链接即触发」路径
10-18 提交 OpenAI 漏洞赏金计划
10-21 OpenAI 复现,P2 升 P1
10-22~23 一个前端修复 + CSP 收紧,另一版本跟进
10-26 双前端确认拦截跨 frame MathLive 消息,关闭 issue,赏金 $5,000
10-28 Parameter 发布完整 writeup

修复本身不复杂:两版 web 前端都拒绝了跨 frame 的 MathLive 消息。官方没有真实滥用报告(uncertain:仅官方口径),整个验证过程在研究者自有账号间受控完成。

HN 上吵什么:$5,000 值不值

细节公开后,Hacker News 讨论里最热的争议不是技术,是价钱:P1 级别、能读私聊的账号接管,赏金 $5,000。高赞观点认为偏低------「别人可能就不报了」。作为对照,同类 Web 级账号接管在其他大厂的项目里拿到六位数美元的并不罕见。

另一个值得注意的提醒来自 Ostorlab 的分析:嵌入 MathLive 的其他产品应当自查------这波披露只证明了 ChatGPT 侧的修复,MathLive 上游的消息处理器是否已修补,writeup 并未给出结论(uncertain)。

这给 AI 产品团队的四堂课

作者总结的防御清单,条条都能直接落进 code review:

  1. postMessage 接收方必须同时验证 event.origin 和 event.source------「消息类型对」不等于「寄信人对」;
  2. 跨窗口的设置消息里不要放 raw HTML------键盘布局这类配置,用结构化数据别用标记字符串;
  3. 内容可能受不可信 frame 影响时,动态创建的文档必须保持 sandbox ------一个缺失的 sandbox 属性就是身份继承的直通车;
  4. CSP 是纵深防御,不是渲染路径的免死金牌------攻击者的 HTML 一旦进了主站,允许名单里任何一个能返回 JS 的第三方端点都是跳板。

再往深一层,是 AI 产品特有的结构性风险:「渲染模型输出」的面(Preview/Artifacts/画布)天然是不可信代码,而「分享」功能负责把不可信输入精确投递到登录用户面前。这两个特性单独看都人畜无害,接缝处就是攻击面。做 LLM 产品的团队,值得把「分享 + 渲染」的组合拉进威胁建模。

安全边界从来不是某一个组件的事------它是整条产品链上每一座桥的总和。这大概就是这篇 writeup 标题「Do the math」的另一次深意:漏洞藏在乘法里,不在加法里。


参考来源

一级来源(原始披露)

  1. Parameter Labs:《Do the Math: How We Took Over ChatGPT Accounts》(Mukul Goyal,2026-10-28)--- www.parameter.ai/labs/we-fou...

二级来源(独立报道与分析,用于交叉核验)

  1. The Hacker News:《A Shared ChatGPT Link Could Run Attacker Code in Your Session and Read Private Chats》(Swati Khandelwal,2026-10-31)--- thehackernews.com/2026/10/a-s...
  2. Simon Willison:《How We Took Over ChatGPT Accounts》(2026-10-31)--- simonwillison.net/2026/oct/31...
  3. Ostorlab:《ChatGPT Shared-Link Account Takeover via MathLive Sandbox Escape》(2026-10-31)--- blog.ostorlab.co/chatgpt-sha...
  4. Hacker News 讨论:We Took over ChatGPT Accounts(297 分 / 145 评论)--- news.ycombinator.com/item?id=503...
  5. breach-signal:《OpenAI patches ChatGPT share-link flaw after disclosure》(2026-10-31)--- breach-signal.com/vulnerabili...

说明:技术细节与时间线以 Parameter Labs 一手 writeup 为准;赏金金额、修复状态、无滥用结论均为官方口径;HN 观点为社区讨论摘录,不代表本站立场。

相关推荐
奈落243 小时前
全局切换器之后:从 ChatGPT 桌面端把聊天、工作、编程并进一个窗口,看“三合一”改了什么、没改什么
chatgpt·工作流·ai 编程
dozenyaoyida1 天前
AI与大模型新闻日报 | 2026-10-30
人工智能·ai·chatgpt·大模型·新闻
LaughingZhu1 天前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
卢卡上学1 天前
WorkBuddy内配置使用Claude、ChatGPT、Gemini、Grop模型
chatgpt·中转站·腾讯workbuddy
shennv8881 天前
ChatGPT Plus订阅后如何使用Codex?CLI安装、额度查询与项目开发实践
chatgpt
sg_knight1 天前
Bug 定位实战:把报错丢给 Codex,它是怎么修的
chatgpt·llm·bug·openai·agent·ai编程·codex
Maynor9962 天前
ChatGPT Pro 额度档位怎么理解:5x / 20x / 50x 使用笔记
ai·chatgpt·教程
玫瑰互动GEO2 天前
GEM优化广告六要素: 从命名一致到落地页双对齐的工程化落地
人工智能·ai·chatgpt·gem优化
shandianchengzi2 天前
【记录】LLM|ChatGPT连接Github并管理
chatgpt·github