Deathray:不可信网站让 Mac 死机的简单方法
一个不可信网站让 Mac 死机的简单方法
不可信网站上的一个 WebGPU shader 就能让 Mac 的图形系统卡死,桌面界面无法使用,直到强制重启为止。受害者只需要点击一个链接。这个问题在 MacOS 上跨浏览器可复现,但在其他操作系统上不行。
试试 Deathray!
下面的按钮会让你的 Mac 死机,也可能会拖慢其他操作系统
在我测试过的其他操作系统上,它只会导致标签页卡死、系统变卡,关掉标签页就恢复正常了。但你的情况可能不同!只有愿意接受电脑死机风险时才点击上面的按钮。
影响范围
我在 MacOS 的 Chrome、Firefox 和 Safari 上都复现了 deathray,但在其他操作系统上无法复现。我只在运行 Tahoe 的 M 系列 MacBook 上测试过;如果你发现其他 Mac 也受影响,欢迎告诉我!
工作原理
deathray 用到了一项相对较新的 Web 技术:WebGPU。WebGPU 提供内置的浏览器 API,网站可以通过它向设备 GPU 提交 shader 运行。它旨在取代 WebGL,已在大多数操作系统的所有主流浏览器中得到支持。
整个 deathray 只需一个小文件就能实现。你可以在这里查看源代码。文件的大部分是脚手架代码,关键部分是 WebGPU shader。
Compute Shader
@group(0) @binding(0) var<storage, read_write> data : array<vec4f>;
@compute @workgroup_size(1) fn compute() {
// no i++, loop spins endlessly
for(var i = 0u; i < 1;) {
data[i+1] = data[i];
}
}
Render Shaders
@group(0) @binding(0) var<storage, read> data : array<vec4f>;
@vertex fn vert(@builtin(vertex_index) vertexIdx : u32)
-> @builtin(position) vec4f {
// attempts to read from same buffer the compute shader writes to
let datum = data[vertexIdx];
return datum;
}
@fragment fn frag(@builtin(position) pos : vec4f)
-> @location(0) vec4f {
return pos;
}
compute shader 中有一个无限忙循环,不断把同一个向量反复复制到缓冲区里。而 vertex shader 依赖的正是 compute shader 正在操作的同一块数据缓冲区。由于 compute shader 一直在忙于循环,vertex shader 就无法继续执行。
这个问题会波及到其他需要 GPU 的进程,尤其是 WindowServer。由于 WebGPU 任务堆积,WindowServer 也随之无响应。具体表现不一定相同:有时还能动鼠标,有时完全卡死;有时出现彩色转圈等待图标,有时屏幕局部会刷出粉红色的花屏。我不太确定是什么导致了这些不同的表现。
有意思的是,此时电脑其他部分完全正常,你甚至能正常 SSH 连进去。但系统里有个 Watchdog 在监控 WindowServer,一旦它长时间无响应,就会触发 kernel panic,电脑自动重启。如果你已经被 deathray 命中且等不及,可以长按电源键强制关机重启,不必等 Watchdog 动手。只希望你的浏览器重启后不会自动恢复那个该死的标签页 :)
先例
苹果其实不是第一次遇到这类问题。2023 年,Imperva 的 Ron Masas 制作了一个类似的恶意 shader,名为 ShadyShader,利用的是 WebGL。ShadyShader 同样用失控的循环来霸占 GPU——构造了巨大的嵌套循环,但严格来说并不是无限循环。
苹果随后发布了 CVE-2023-40441,CVSS 评分为 6.5(中危)。作为缓解措施,苹果增强了输入校验,以便更好地检测失控循环。
不过在 WebGPU 中,这套输入校验似乎没那么严格——deathray 里的无限循环几乎一眼就能看出来。但归根结底,检测无限循环是一场必输的博弈,halting problem 绕不过去。需要更完善的机制来抢占无响应的 shader,尤其是当这些 shader 在运行不可信代码时。我测试过 deathray 的其他操作系统,都能正确处理这一点。
我猜苹果在修复这类问题时所面临的困难,部分原因在于 M 系列芯片的架构。操作系统内核无法直接抢占 GPU,实际由一个名为 ASC 的协处理器来完成 GPU 处理,内核通过它与之通信。所有 GPU 抢占逻辑都写在 ASC 的固件里。Asahi Lina 有一篇关于 M 系列 GPU 的精彩文章,更详细地剖析了这一架构。
deathray 是怎么被发现的?
我以最老派的方式发现了这个问题:纯属意外!当时我在 Recurse Center 学习 WebGPU,不小心写了个死循环。电脑直接卡死让我吃了一惊,我本能地试了试"是不是每次都会这样"——果然。我不可能是第一个撞上这个坑的人。
漏洞披露
我在 2026 年 7 月 27 日将问题报告给了 Apple Security。Apple 很快复现了问题并表示会修复,还给出了修复时间表,但标注为机密,所以我这里就不写了。
然而 2026 年 8 月 26 日,Apple 突然改口,称"未发现该报告存在任何安全影响",也未"导致产品发生任何变更"。他们说该报告将转交另一个团队进行"潜在增强评估"。在我看来,这意味着修复优先级会非常低,甚至可能根本不会被处理。考虑到 ShadyShader 被标记为 6.5 分的中危问题,这个态度确实让人困惑。
话虽如此,"什么才算安全问题"确实值得讨论。我聊过的安全研究员大多认同 Apple 的立场。用 Apple 的话说,"结果是崩溃、卡死或可恢复的数据丢失,我们不认为这属于安全问题。"从技术层面讲,我觉得他们说的也没错。
但我聊过的非安全领域的人,大多对这种定性和 Apple 不优先修复的态度感到意外。我觉得普通用户对浏览器有相当强的信任感——也许是过于天真的信念:点一个链接最多只是让电脑慢一点,关掉标签页就恢复了。deathray 这种东西以非常直观的方式打破了这种信任,我认为大多数用户会把它视为安全问题。
我期望看到的
deathray 的严重程度当然远不及沙箱逃逸、RCE 或数据泄露。但它上手门槛极低(只需要让人点一个链接),所以搞起事来会相当烦人。如果被恶意使用,我觉得它就像一个更恶毒的 Rickroll,希望 Apple 能尽快修复。(Apple 拜托,修复方案别是默认禁用 WebGPU 啊!我已经爱上 WebGPU 了 💚)
不过在 Apple 修复之前,希望大家能拿它玩点无害的花样。我很想看到这样的 deathray 游戏礼物:游戏输了,你的 Mac 就会死机(前提是用户提前自愿开启)。这算是「游戏中死亡,现实中也会死」的温和版本。
玩得开心,但也请手下留情!
此致,
Auberon López(they/them)