Echo's blog
Echo's blog
· 1 min read · 资讯

一万个GitHub仓库正在悄悄传播木马

一次无意中的发现#

一位独立安全研究员的日常排查,在几周前出现了一个令人不安的转折。他习惯性地在 Google 上搜索自己项目的名字,想看看有没有人未经授权地复制和分发代码。搜索结果的第一页,出现了一个似曾相识的 GitHub 仓库——项目名和他的作品几乎一样,README 也大段复制了他项目中的描述文字。

但往下翻了几行之后,他愣住了。README 底部附了一个下载链接,指向一个 ZIP 压缩包,文件名完全陌生。凭借安全从业者的直觉,他没有直接下载,而是先用 VirusTotal 扫了一遍。结果触目惊心:那个压缩包被多家杀毒引擎标记为 Trojan 木马。

他随即点进这个仓库的提交记录,随后发现的模式让他意识到——这根本不是孤例。

四万分之一#

这名研究员开始思考一个更宏观的问题:这类恶意仓库在 GitHub 上到底有多少?直接搜索关键词无异于大海捞针,恶意项目们散落在平台各处,彼此之间没有任何显式关联。

他换了一种思路。GitHub 的公开事件流每天汇聚着海量的推送行为——他拉取了 5 天内约 1600 万条 commit push 事件,然后按仓库维度进行聚合,筛选出那些更新频率异常的项目:每天推送 1 到 24 次的仓库,共计约 4 万个。

这个数字本身已经不小,但真正让人不安的是下一步。他逐一检查了这些高频更新仓库的内容模式,结果发现——大约有四分之一符合他之前看到的那种恶意特征。四万个中的一万个,这个数字以极其直接的方式摊开在面前。

一万个仓库,分布在不同账户下,各自有条不紊地运作着。

它们有一个共同模式#

当研究员把这一万个仓库放在一起分析时,一个高度统一的操作模板浮出水面。这些仓库并非彼此 fork——它们有着不同的项目名、不同的贡献者头像,乍看之下是完全独立的正常项目。但 README 文件出卖了它们。

每一个仓库都采用了完全相同的手段:从某个合法开源项目中大量复制代码和文档,构建出一个外表完全正常的项目页面,然后在 README 的某个位置嵌入一个指向 ZIP 压缩包的下载链接。这个压缩包的内容结构也高度一致——一个 Application.cmdLauncher.cmd 脚本、一个 loader.exeluajit.exe 可执行文件,再加上一个扩展名为 .cso.txt 的随机命名数据文件。VirusTotal 对整包扫描的检测率并不低,但奇怪的是,如果单独提取压缩包内某个文件的独立链接去查,结果往往显示为零检出——这也解释了为什么它们能绕过不少自动化防御。

更让人后背发凉的是这些仓库的更新行为。每个仓库每隔几小时就会执行一次推送:删除上一次的 commit,然后用完全相同的内容重新提交一遍。唯一的变动是 README 文件——虽然内容几乎不变,但这个擦除重写的动作本身,似乎正是为了让仓库保持一种”正在积极维护”的假象。活跃的仓库不容易被注意,被清扫的风险也更低。

GitHub 的沉默#

发现这一万名”潜伏者”之后,研究员按照平台的规定流程向 GitHub 安全团队提交了举报。他详细列出了第一批恶意仓库的链接、检测证据和模式分析。随后是等待。

几周过去了,GitHub 的第一次回复才姗姗来迟。又过了一个月左右,第一批被举报的仓库才真正被移除。这还只是最初上报的那一小批——而总数是一万个。即便处理速度维持在这个节奏,也需要数年才能完成一轮完整的清扫。更不用说在此期间,新的恶意仓库可能又冒出了成百上千。

整个过程中,这些仓库没有表现出任何防御性反应。它们就这样安静地躺在 GitHub 上,持续更新,持续诱骗着那些通过搜索引擎找上门来的开发者。对于一名习惯用 Google 搜索项目名的开发者来说,看到自己项目的名字出现在搜索结果前列、点进一个外貌正常的仓库、下载一个 README 里声称的”依赖文件”——这个过程几乎是下意识的。而木马的传播,就藏在这个下意识的瞬间里。

一万个钓钩,散布在开源世界的每一个角落。它们不攻破任何系统,不利用任何零日漏洞,它们等待的只是开发者的一次习惯性点击。在平台的安全防线真正跟上来之前,这或许才是最棘手的部分。

来源:Hacker News

Related Posts

Comments

Copied
Copied to clipboard