Incident Report: CVE-2024-YIKES

Incident Report: CVE-2024-YIKES

事件报告:CVE-2024-YIKES

Report filed: 03:47 UTC Status: Resolved (accidentally) Severity: Critical → Catastrophic → Somehow Fine Duration: 73 hours Affected systems: Yes 报告提交时间: 03:47 UTC 状态: 已解决(意外地) 严重程度: 严重 → 灾难性 → 居然没事了 持续时间: 73 小时 受影响系统:

Executive Summary: A security incident occurred. It has been resolved. We take security seriously. Please see previous 14 incident reports for details on how seriously. 执行摘要: 发生了一起安全事件。目前已解决。我们非常重视安全性。请参阅之前的 14 份事件报告,了解我们到底有多“重视”。

Summary: A compromised dependency in the JavaScript ecosystem led to credential theft, which enabled a supply chain attack on a Rust compression library, which was vendored into a Python build tool, which shipped malware to approximately 4 million developers before being inadvertently patched by an unrelated cryptocurrency mining worm. 摘要: JavaScript 生态系统中一个被入侵的依赖项导致了凭据被盗,进而引发了针对一个 Rust 压缩库的供应链攻击。该库被集成(vendored)到一个 Python 构建工具中,最终向约 400 万开发者分发了恶意软件,直到被一个无关的加密货币挖矿蠕虫意外修复。


Timeline 时间线

Day 1, 03:14 UTC — Marcus Chen, maintainer of left-justify (847 million weekly downloads), reports on Twitter that his transit pass, an old laptop, and “something Kubernetes threw up that looked important” were stolen from his apartment. He does not immediately connect this to package security. 第 1 天,03:14 UTCleft-justify(每周下载量 8.47 亿次)的维护者 Marcus Chen 在 Twitter 上报告称,他的公交卡、一台旧笔记本电脑以及“Kubernetes 吐出来的看起来很重要的东西”从公寓里被盗。他没有立即将此事与软件包安全联系起来。

Day 1, 09:22 UTC — Chen attempts to log into the nmp registry. His hardware 2FA key is missing. He googles where to buy a replacement YubiKey. The AI Overview at the top of the results links to “yubikey-official-store.net,” a phishing site registered six hours earlier. 第 1 天,09:22 UTC — Chen 尝试登录 npm 注册表。他的硬件双重验证(2FA)密钥丢失了。他用谷歌搜索在哪里购买替换的 YubiKey。搜索结果顶部的 AI 概览链接到了“yubikey-official-store.net”,这是一个六小时前刚注册的钓鱼网站。

Day 1, 09:31 UTC — Chen enters his nmp credentials on the phishing site. The site thanks him for his purchase and promises delivery in 3-5 business days. 第 1 天,09:31 UTC — Chen 在钓鱼网站上输入了他的 npm 凭据。网站感谢他的购买,并承诺在 3-5 个工作日内送达。

Day 1, 11:00 UTCleft-justify@1.0.1 is published. The changelog reads “performance improvements.” The package now includes a postinstall script that exfiltrates .npmrc, .pypirc, ~/.cargo/credentials, and /.gem/credentials to a server in a country the attacker mistakenly believed had no extradition treaty with anyone. 第 1 天,11:00 UTCleft-justify@1.0.1 发布。更新日志写着“性能改进”。该软件包现在包含一个安装后脚本,会将 .npmrc、.pypirc、/.cargo/credentials 和 ~/.gem/credentials 窃取并发送到某个国家的服务器,攻击者错误地认为该国与任何国家都没有引渡条约。

Day 1, 13:15 UTC — A support ticket titled “why is your SDK exfiltrating my .npmrc” is opened against left-justify. It is marked as “low priority - user environment issue” and auto-closed after 14 days of inactivity. 第 1 天,13:15 UTC — 一个标题为“为什么你们的 SDK 在窃取我的 .npmrc”的支持工单被提交给 left-justify。该工单被标记为“低优先级 - 用户环境问题”,并在 14 天无活动后自动关闭。

Day 1, 14:47 UTC — Among the exfiltrated credentials: the maintainer of vulpine-lz4, a Rust library for “blazingly fast Firefox-themed LZ4 decompression.” The library’s logo is a cartoon fox with sunglasses. It has 12 stars on GitHub but is a transitive dependency of cargo itself. 第 1 天,14:47 UTC — 在被窃取的凭据中,包括了 vulpine-lz4 的维护者,这是一个用于“极速、火狐主题 LZ4 解压”的 Rust 库。该库的标志是一只戴墨镜的卡通狐狸。它在 GitHub 上只有 12 颗星,但却是 cargo 本身的传递依赖项。

Day 1, 22:00 UTC — vulpine-lz4 version 0.4.1 is published. The commit message is “fix: resolve edge case in streaming decompression.” The actual change adds a build.rs script that downloads and executes a shell script if the hostname contains “build” or “ci” or “action” or “jenkins” or “travis” or, inexplicably, “karen.” 第 1 天,22:00 UTCvulpine-lz4 0.4.1 版本发布。提交信息是“修复:解决流式解压中的边缘情况”。实际的更改添加了一个 build.rs 脚本,如果主机名包含“build”、“ci”、“action”、“jenkins”、“travis”或者莫名其妙的“karen”,它就会下载并执行一个 shell 脚本。

Day 2, 08:15 UTC — Security researcher Karen Oyelaran notices the malicious commit after her personal laptop triggers the payload. She opens an issue titled “your build script downloads and runs a shell script from the internet?” The issue goes unanswered. The legitimate maintainer has won €2.3 million in the EuroMillions and is researching goat farming in Portugal. 第 2 天,08:15 UTC — 安全研究员 Karen Oyelaran 在她的个人笔记本电脑触发了有效载荷后,注意到了这个恶意提交。她开了一个标题为“你们的构建脚本从互联网下载并运行 shell 脚本?”的 issue。该 issue 无人回应。合法的维护者中了 230 万欧元的欧洲百万彩票,正在葡萄牙研究养羊。

Day 2, 10:00 UTC — The VP of Engineering at a Fortune 500 snekpack customer learns of the incident from a LinkedIn post titled “Is YOUR Company Affected by left-justify?” He is on a beach in Maui and would like to know why he wasn’t looped in sooner. He was looped in sooner. 第 2 天,10:00 UTC — 一家财富 500 强 snekpack 客户的工程副总裁从一篇名为“你的公司受到 left-justify 的影响了吗?”的 LinkedIn 帖子中得知了此事。他当时正在茂宜岛的海滩上,想知道为什么没有早点通知他。其实他早就被通知了。

Day 2, 10:47 UTC — The #incident-response Slack channel briefly pivots to a 45-message thread about whether “compromised” should be spelled with a ‘z’ in American English. Someone suggests taking this offline. 第 2 天,10:47 UTC — #incident-response Slack 频道短暂地转向了一个包含 45 条消息的讨论串,讨论美式英语中“compromised”是否应该拼写为带‘z’的形式。有人建议线下讨论。

Day 2, 12:33 UTC — The shell script now targets a specific victim: the CI pipeline for snekpack, a Python build tool used by 60% of PyPI packages with the word “data” in their name. snekpack vendors vulpine-lz4 because “Rust is memory safe.” 第 2 天,12:33 UTC — 该 shell 脚本现在瞄准了一个特定受害者:snekpack 的 CI 流水线。snekpack 是一个 Python 构建工具,被 60% 名称中带有“data”一词的 PyPI 软件包使用。snekpack 集成了 vulpine-lz4,因为他们认为“Rust 是内存安全的”。

Day 2, 18:00 UTC — snekpack version 3.7.0 is released. The malware is now being installed on developer machines worldwide. It adds an SSH key to ~/.ssh/authorized_keys, installs a reverse shell that only activates on Tuesdays, and changes the user’s default shell to fish (this last behavior is believed to be a bug). 第 2 天,18:00 UTCsnekpack 3.7.0 版本发布。恶意软件现在正被安装到全球开发者的机器上。它向 ~/.ssh/authorized_keys 添加了一个 SSH 密钥,安装了一个仅在周二激活的反向 shell,并将用户的默认 shell 更改为 fish(最后这个行为被认为是一个 bug)。

Day 2, 19:45 UTC — A second, unrelated security researcher publishes a blog post titled “I found a supply chain attack and reported it to all the wrong people.” The post is 14,000 words and includes the phrase “in this economy?” seven times. 第 2 天,19:45 UTC — 第二位无关的安全研究员发表了一篇博客,标题为“我发现了一起供应链攻击,并向所有错误的人报告了它”。这篇文章有 14,000 字,其中七次提到了“在这种经济环境下?”这句话。

Day 3, 01:17 UTC — A junior developer in Auckland notices the malicious code while debugging an unrelated issue. She opens a PR to revert the vendored vulpine-lz4 in snekpack. The PR requires two approvals. Both approvers are asleep. 第 3 天,01:17 UTC — 奥克兰的一名初级开发人员在调试一个无关问题时注意到了恶意代码。她提交了一个 PR,旨在回滚 snekpack 中集成的 vulpine-lz4。该 PR 需要两次批准。但两名审批者都在睡觉。

Day 3, 02:00 UTC — The maintainer of left-justify receives his YubiKey from yubikey-official-store.net. It is a $4 USB drive containing a README that says “lol.” 第 3 天,02:00 UTCleft-justify 的维护者收到了来自 yubikey-official-store.net 的 YubiKey。那是一个价值 4 美元的 U 盘,里面有一个写着“lol”的 README 文件。

Day 3, 06:12 UTC — An unrelated cryptocurrency mining worm called cryptobro-9000 begins spreading through a vulnerability in jsonify-extreme, a package that “makes JSON even more JSON, now with nested comment support.” The worm’s payload is unremarkable, but its propagation mechanism includes running npm update and pip install —upgrade on infected machines to maximize attack surface for future operations. 第 3 天,06:12 UTC — 一个名为 cryptobro-9000 的无关加密货币挖矿蠕虫开始通过 jsonify-extreme 中的漏洞传播,该软件包声称“让 JSON 变得更 JSON,现在支持嵌套注释”。该蠕虫的有效载荷平淡无奇,但其传播机制包括在受感染机器上运行 npm updatepip install --upgrade,以最大限度地扩大未来行动的攻击面。

Day 3, 06:14 UTC — cryptobro-9000 accidentally upgrades snekpack to version 3.7.1, a legitimate release pushed by a confused co-maintainer who “didn’t see what all the fuss was about” and reverted to the previous vendored version of vulpine-lz4. 第 3 天,06:14 UTCcryptobro-9000 意外地将 snekpack 升级到了 3.7.1 版本。这是一个由一位困惑的共同维护者推送的合法版本,他“没看懂大家在闹什么”,并回滚到了之前集成的 vulpine-lz4 版本。

Day 3, 06:15 UTC — The malware’s Tuesday reverse shell activates. It is a Tuesday. However, the shell connects to a command-and-control server that was itself compromised by cryptobro-9000 and swapping so hard it is unable to respond. 第 3 天,06:15 UTC — 恶意软件的周二反向 shell 激活了。今天是周二。然而,该 shell 连接到的命令与控制服务器本身已被 cryptobro-9000 入侵,且由于内存交换过于频繁而无法响应。

Day 3, 09:00 UTC — The snekpack maintainers issue a security advisory. It is four sentences long and includes the phrases “out of an abundance of caution” and “no evidence of active exploitation,” which is technically true because evidence was not sought. 第 3 天,09:00 UTCsnekpack 维护者发布了一份安全公告。公告只有四句话,包含了“出于谨慎考虑”和“没有证据表明存在主动利用”等短语,这在技术上是正确的,因为他们根本没去寻找证据。

Day 3, 11:30 UTC — A developer tweets: “I updated all my dependencies and now my terminal is in fish???” The tweet receives 47,000 likes. 第 3 天,11:30 UTC — 一位开发者发推文称:“我更新了所有的依赖项,现在我的终端变成了 fish???”该推文获得了 47,000 个赞。

Day 3, 14:00 UTC — The compromised credentials for vulpine-lz4 are rotated. The legitimate maintainer, reached by email from his new goat… 第 3 天,14:00 UTCvulpine-lz4 被泄露的凭据已重置。合法的维护者通过电子邮件联系上了,他正忙于他的新山羊……