10月19日,一名攻击者用一位贡献者的GitHub账号,替换了OVHcloud命令行工具五个已发布版本的下载归档。OVHcloud表示,该账号已被劫持,替换上去的文件是一个专门构建的版本,用来窃取运行它的机器磁盘上存储的密钥。
![]()
这些文件在GitHub上存活了最长94分钟,从UTC时间12:47到14:21。受影响的只有在这个窗口内安装或更新OVHcloud CLI的人,路径不校验哈希,覆盖macOS、Linux x86_64与arm64、Windows x86_64。
OVHcloud删除了被替换的归档,当晚发布了干净的v0.16.0,作为不可变版本发布,其文件GitHub不允许任何人修改。源代码、发布标签和公司的构建流水线均未被触碰:恶意构建只是对一个更晚提交的普通go build,直接上传到4月至9月间发布的版本上。
谁暴露了
在v0.15.0上,攻击者替换了六个文件:macOS x86_64与arm64归档、Linux x86_64与arm64归档、Windows x86_64归档,以及checksums.txt,使公布的哈希与新二进制匹配。同样的六个文件现在也从v0.11.0到v0.14.0中消失了。Linux i386、Windows i386、Windows arm64和WebAssembly构建在每个版本上都未被改动。
OVHcloud将v0.11.0至v0.15.0列为已受损,v0.10.0为干净。这五个版本发布于4月14日至9月16日之间,因此在周一12:47 UTC之前安装且此后未更新的副本是原始版本。
如果你在该窗口内、在以下平台之一上做了这些操作,你就拿到了被替换的文件:
- 运行了官方安装脚本(curl -fsSL https://raw.githubusercontent.com/ovh/ovhcloud-cli/main/install.sh | sh)。它会下载最新发布归档并安装,从不校验哈希。
- 从五个版本中任一版本的GitHub发布页面下载了归档。
- 运行了从发布下载URL获取归档、未固定哈希的CI任务或构建步骤。
- 在由脚本或手动安装工具的macOS或Linux机器上,从v0.12.0、v0.13.0或v0.14.0安装运行了CLI自带的升级命令。该命令下载归档并替换二进制,不做哈希校验。在Homebrew或go install环境下,它只打印要运行的命令。
如果你做了以下操作,则没有中招:
- 用Homebrew安装。窗口期内生效的cask固定了每个归档的原始SHA-256,Homebrew会拒绝哈希不匹配的下载,因此brew install或brew upgrade会失败而不是安装被替换的文件。部分早期报道将Homebrew列为暴露路径,但The Hacker News核查了tap的提交历史:从9月16日的v0.15.0 cask到周一晚间的v0.16.0 cask之间没有任何改动。
- 使用go install或从源码构建。v0.15.0标签仍指向其9月的提交760fd72。
- 拉取了Docker镜像。其latest标签最后推送于9月21日,即换包前四周,截至周二未重建。
- 在周一12:47 UTC之前安装,且窗口期内未更新。
如何辨别
发现换包的客户用go version -m从新的v0.15.0 Linux arm64二进制中提取构建信息,该命令读取文件而不运行它,并将结果发在GitHub issue中。恶意构建有三个标记:
- 模块行显示v0.15.1-0.20261013083505-5ead8ef9b43d+dirty,这是一个伪版本,Go为未打标签提交的构建生成的替代字符串,此处来自10月13日。真正的发布带有其标签号:OVHcloud干净的v0.16.0构建显示v0.16.0+dirty。
- 记录的提交是5ead8ef,而非v0.15.0标签指向的760fd72。
- 存在一行-ldflags="-s -w"。OVHcloud的发布流水线使用一个版本标志构建,Go不会将其记录在flags中,因此真正的发布完全不显示-ldflags行。
流传的建议称任何标记为+dirty或带有vcs行的构建都是恶意的,这会误标OVHcloud自己的发布。The Hacker News对干净的v0.16.0 Linux x86_64二进制运行了同样的命令:它报告v0.16.0+dirty、vcs.modified=true以及构建所用的提交。
唯一公布哈希的被替换文件是v0.15.0 Linux arm64归档:
- SHA-256(被替换归档):3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb
- SHA-256(原始归档):5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0
没有版本标志的构建会将其版本报告为undefined,但运行可疑二进制来查明并不可取。
该做什么
OVHcloud创始人Octave Klaba周一晚间在X上写道,任何受影响的人都应更换磁盘上存储的每一个密钥。
根据其文档,CLI将OVHcloud API凭据保存在~/.ovh.conf中,并从环境变量读取,该建议覆盖磁盘上的所有其他内容,而不仅是这些文件。
- 如果你运行了被替换的构建,或无法判断,请将该机器上可读的每个密钥视为已暴露并轮换。调查此事件的OpenSourceMalware补充:从另一台机器上操作。
- 删除二进制并安装v0.16.0。该版本不可变并带有发布证明,即其文件的签名记录。更新会替换程序,但不会撤销已被复制的密钥,这就是轮换要放在第一位的原因。
- 按照GitHub文档,用gh release verify-asset v0.16.0 FILE对照发布校验下载的归档。
OVHcloud尚未说明该二进制读取哪些文件、将它们发送到哪里,或下载了多少份,也没有任何被替换归档的副本被公开分析。公司承诺将在未来几天发布详细的复盘报告。
事情是怎么发生的
任何对GitHub仓库有写权限的人都可以删除发布附带的文件,并以相同名称上传新文件,除非启用了发布不可变性,下载URL不会改变。
该设置自2025年10月起普遍可用,锁定发布的文件和标签,但只保护启用之后创建的发布。
OVHcloud此前未启用它。据Next引用,Klaba在周一晚间的第二条帖子中写道,问题源于不可变性选项未激活,因此有相应权限的用户可以直接在GitHub上修改现有发布,而不受公司CI/CD流水线的任何检查。该选项现已启用,流水线本身未受影响。
五个旧版本现在只提供攻击者未触碰的四个归档。
据OpenSourceMalware根据GitHub服务器端记录构建的时间线,上传是通过一位贡献者的账号进行的,其已合并的工作存在于OVHcloud的文档仓库中,且该人并非组织的公开成员。
发布工作流从未运行:运行列表显示10月16日至周一16:00 UTC推送v0.16.0标签之间没有任何工作流。Klaba在第一篇帖子中写道,初步检查未发现其他仓库受影响,OVHcloud尚未说明该账号的凭据是如何被获取的。
一位客户的CI任务发现了换包,因为它固定了Linux arm64归档的SHA-256并开始失败。由于仓库没有私密报告渠道,该客户提交了公开issue,据OpenSourceMalware的时间线为13:50 UTC,OVHcloud约半小时后于14:21 UTC(巴黎时间16:21)删除了被替换的文件。v0.16.0随后于17:16 UTC发布,由公司的ovh-cds账号发布并带有签名标签。
GlassWorm的疑问
OpenSourceMalware将该账号与GlassWorm联系起来,这是一个将代码隐藏在不可见Unicode字符中、并从Solana钱包交易的memo字段获取下一阶段的恶意活动。研究人员发现,该账号的四个个人仓库在3月5日和6日被强制推送,加入了一个带有此类加载器的修订提交。
该加载器读取的钱包正是GlassWorm的ForceMemo活动中提到的那个,该活动在3月用窃取的GitHub令牌将恶意软件强制推入数百个Python仓库。The Hacker News确认,该加载器文件仍在其中一个仓库中,哈希与研究人员公布的一致。
是否为同一行为者所为,研究人员写道这是“我们的推断”。共享账号是联系所在,10月二进制中的任何内容都未与GlassWorm关联,因为没有保留其副本。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.