找到恶意软件包:Go 语言生态系统中的供应链攻击是怎样的?

近期发生的严重的 SolarWinds 攻击事件和新型 “依赖混淆“攻击,让供应链攻击成为讨论焦点:攻陷供应链中不太安全的元素,导致更安全的目标遭攻陷。

供应链攻击的流行目标一直都是流行编程语言的很多包管理系统,如 NPM (JavaScript)、Rubygems (Ruby) 以及 PyPI (Python)。这些系统常年来遭受恶意攻击,攻击者上传恶意包并等待受害者安装。

目前为止,尚未看到关于 Go 生态系统的供应链攻击情况。鉴于 Go 语言是我的新宠,我决定自己做一些调查。

好在依赖混淆并未Go 开发人员需要担心的攻击,因为导入数据包时来源总是显而易见的,因此当 Go 得到外部依赖关系时,不会遇到如何获取的困扰:

找到恶意软件包:Go 语言生态系统中的供应链攻击是怎样的?

然而,Go 开发人员可能会遇到 “误植域名 (typosquatting)“的情况,即攻击者利用人们经常从键盘按下错误按键的事实。攻击者可以注册 github.com 的常用打字错误,在主机域名上执行误植域名攻击,或者只是在 GitHub 或其它程序包主机上注册一个新用户,而常见的打字错误是程序包所有人的用户名。

鉴于此,我构建了一款工具,用于找到潜在在野 typosquat 程序包:

  1. 大量获取 Go 包导入路径列表(如 github.com/stretchr/testify)
  2. 排列每个唯一程序包的用户名称,获得潜在的typosquat列表
  3. 检查平台上是否存在其中任何typosquat用户
  4. 如找到了潜在的typosquat用户,则检索其所有存储库
  5. 记录名称和所检查的原始程序包名称一样的仓库

结果,我构建了一款工具,名为 “pkgtwist”,如有兴趣尝试捕获恶意 Go 程序包,可访问:https://gitlab.com/michenriksen/pkgtwist。

排列

pkgtwist 最重要的部分很可能是生成良好的用户名排列,从而增加检测到typosquat 的几率。一番研究后,我进入zntrio/typogenerater,它看似是生成潜在用户名输入错误的完美程序包。该程序包执行了非常长的排列策略,我从中挑选了一些,因此 pkgtwist 仅检查我认为最可能是输入错误的情况即可:

缺失:删除单一字符(缺少按键, stretchr => strechr)

重复:重复字符(两次按键,gobuffalo => gobuffallo)

Bitsquatting:很可能的位翻转错误 (stretchr => strftchr)

换位:交换相邻字符(按错误顺序按键,stretchr => strethcr)

这意味着,如果 pkgtwist 获得程序包 github.com/stretchr/testify 作为输入,那么它会检查如下用户是否存在于 GitHub 上,如存在,则检查是否拥有一个名为 testify 的仓库:

tretchr sretchr stetchr strtchr strechr strethr stretcr stretch sstretchr sttretchr strretchr streetchr strettchr stretcchr stretchhr stretchrr rtretchr qtretchr ptretchr wtretchr vtretchr utretchr ttretchr suretchr svretchr swretchr spretchr sqretchr srretchr ssretchr stsetchr stpetchr stqetchr stvetchr stwetchr sttetchr stuetchr strdtchr strgtchr strftchr stratchr strctchr strbtchr streuchr strevchr strewchr strepchr streqchr strerchr streschr stretbhr stretahr stretghr stretfhr stretehr stretdhr stretcir stretcjr stretckr stretclr stretcmr stretcnr stretcor stretchs stretchp stretchq stretchv stretchw stretcht stretchu tsretchr srtetchr stertchr strtechr strecthr strethcr stretcrh

主题

接下来是找到程序包列表并进行检查。最初我以为可以找到类似于“前几大 Go 程序包”的列表,但并未如愿,因此对托管在 github.com 和 gitlab.com 上的来自 Go Module Index(共731个程序包)的程序包运行了 pkgtwist。

结果找到恶意软件包:Go 语言生态系统中的供应链攻击是怎样的?

对这731个程序包运行了几个小时后,pkgtwist 筛选出7个可能存在 typosquat的程序包进行进一步的调查。说实话虽然我本来认为会更多,但目前来看 Go 生态系统尚未遭恶意 typosquat 程序包感染,这一点让人高兴。

然而,有几个 typosquat 程序包映入我的眼帘。

github.com/siruspen/logrus

sirupsen 提供的 logrus 包是很多 Go 项目都在使用的非常流行的日志记录程序包(在 GitHub 上获得 17.3k 个star),从而成为 typosquat 供应链攻击的目标。因此当我看到用户 siruspen(注意字母替换)具有一个名称类似的仓库时,快速查看了它的目的。

结果发现该项目是原始 logrus 仓库的 fork,因此将二者做比对非常容易。在本文成稿之时,这个潜在的 typosquat 仓库中添加的唯一内容是一个配有单独的 PrintIn 调用的很小的 init 函数:

找到恶意软件包:Go 语言生态系统中的供应链攻击是怎样的?

虽然从各个角度来讲,它并非恶意,但未来很可能会被所有人快速修改,因此我肯定会关注这个仓库。同时建议使用 logrus 的用户确保自己使用的是真正的程序包!

github.com/utfave/cli

Urfave/cli是构建 CLI 项目的流行 Go 程序包(在 GitHub 上获得15.4k个star)。因此当我看到用户 utfave 也拥有一个名为 cli 的仓库时,警钟敲响并进一步调查。

结果发现,倒数第二个 commit 引入了一个非常可疑的 init 函数:

找到恶意软件包:Go 语言生态系统中的供应链攻击是怎样的?

看起来作者 utfave 想要了解使用他们的 urfave/cli 版本的机器的主机名、操作系统和架构。该函数提取了系统信息,然后通过 HTTP 调用添加到某互联网公司的 IP 地址 122.51.124.140,并将该系统信息添加为 URL 参数。

虽然通过该代码无法获得对系统的访问权限,但非常可疑,收集了这些信息,他们就能发现某个有价值或感兴趣的系统,然而迅速更改此代码,通过反向shell 进行回调。

我已将问题告知 GitHub并希望能在不久之后撤销该仓库。在此之前,我建议 urfave/cli 用户仔细检查是否使用了“误植域名“版本。

结论

虽然这个小小的研究项目并未涵盖所有的 Go 程序包,但足以粗略了解到 Go 生态系统中的供应链攻击情况。Siruspen/logrus 和 utfave/cli 仓库仅仅是我认为可疑的7个被标记出的仓库,我会持续关注余下项目,因为从理论上将讲,它们随时可能转变为恶意仓库。

我认为相比其它编程语言,Go语言的情况更好,因为每次程序包被使用时,其来源都会被明确地写出来,但代码编辑器自动化将使“误植域名“攻击更可能发生,开发人员常常不会手动编写导入路径。例如,如果 VS Code 的 Go 扩展被安装,那么开发人员一般只会在第一次使用时输入程序包导入,之后当该程序包名称被使用时,编辑器将会自动在其它文件中添加导入。如果开发人员在第一次错误地输入导入路径,那么恶意程序包会被引入并在 Go 项目中驻留很久。

资料专区

《手撕GO语言》,从 基础数据类型、流程控制、符合数据类型、函数、包、结构体、方法、并发、测试、常用标准库等15个模块做了详细的讲解,219页的文档,需要的朋友点击 阅读原文 领取网盘链接和提取码。

找到恶意软件包:Go 语言生态系统中的供应链攻击是怎样的?

领取资料请戳:https://iiv.h5.xeknow.com/s/1ueGrH 【微信打开领取网盘链接和提取码】

文章转自奇安信代码卫士

https://codesafe.qianxin.com

相关新闻

历经多年发展,已成为国内好评如潮的Linux云计算运维、SRE、Devops、网络安全、云原生、Go、Python开发专业人才培训机构!