LWN: Git中的一个漏洞!
关注了就能看到更多这么棒的文章哦~
A vulnerability in Git
By Jake Edge
March 10, 2021
DeepL assisted translation
https://lwn.net/Articles/848935/
3 月 9 日,Git(知名的分布式版本控制系统)中公开了一个严重的潜在漏洞。漏洞的详细描述中有很多限定词,因此看起来它的适用条件非常严苛,事实也确实是这样。因此它并不是那么令人担忧,但这并不绝对。与大多数漏洞一样,它是否会被利用取决于软件的使用方式和运行环境。
在对一个精心制作来利用该漏洞(CVE-2021-213)的仓库进行 clone 时,可能会在本地系统上发生非法代码执行(code execution on the local system)。前提条件之一是要安装了某种 Git filter。Filters 允许本地文件系统中的 Git 仓库和远程仓库中过滤掉一部分文件;"smudge" filter 用在从 repository 中提取 blobs(二进制对象)并存储到当前工作目录中的过程中,而 "clean" filter 则可以在将文件提交到 repository 时对其进行修改。需要使用哪种类型的 filter,取决于打算进行什么类型的转换。Git 大文件存储(LFS)是一个很常用的扩展(其中使用了 smudge 和 clean filter),Windows 版本的 Git 默认就安装了 LFS。
使用 filter 时可以将一些 Git 操作的处理延后,这样一来那些需要长期运行的 filter 动作可以在后台进行。例如,Git LFS 可能需要在通过网络来复制一个大文件从而完成 git checkout 操作。不过,这个延后的动作就改变了 Git 正常处理文件和目录的顺序。这就意味着缓存的信息在被用到时可能已经失效了,这正是漏洞出现的原因。
为了减少调用 lstat()的次数,Git 维护了一个 "lstat cache"。如果在文件被 checkout 的过程中发生了路径冲突(path collision,即两个文件的路径和文件名都相同),例如两个名称中仅有大小写不同的文件被 checkout 到一个不区分大小写的文件系统中,那么这个 cache 就可能是错误的。这通常不会导致问题,因为 checkout 是按照顺序进行的,所以就算碰上缓存错误了,但是此时 cache 实际上也用不上。
然而,如果 checkout 中某些动作被 filter 延后了,那么就会有风险了。在查询 cache 时,cache 中的文件的类型可能发生了变化,如果这种变化是由攻击者精心构造的,那么就会出现恶意攻击行为了。修复该漏洞的 patch中是这样描述的:
但是, checkout 机制中有一些情况并不总是遵循 index 顺序的。具体来说:checkout-index 会按照命令行上(或 stdin)上出现的顺序来写入 path 信息,而 delayed checkout 功能(用在某个需要长时间运行的 filter 进程回复 "status=delayed")则会推迟一些内容的 checkout 操作,从而导致 checkout 顺序变化了。
当我们必须不按顺序 checkout 某个文件时并且 lstat() cache 此时是 invalid 的(由于之前提到的路径碰撞),那么 checkout_entry() 可能最终用到的就是这个 invalid 的数据,并[相信] 这个文件名之前的那串路径都是真实的目录,从而被欺骗了。比如目录部分实际上是一个普通文件,那么用户会得到一个错误。"fatal: unable to create file 'foo/bar'. Not a directory"。但如果目录部分被换了一个符号链接[symbolic link],那么 checkout 动作实际上可能最终会跟随符号链接将文件写在一个错误的地方,甚至是在 git repository 之外的位置。delayed checkout 就会受这个影响,它可能会被攻击者用来制作出有问题的 repository,等人们 clone 时进行写破坏。
修复时人们考虑了几种方案,比如在进行不按顺序的 checkout 操作时禁用 cache,或者对文件名进行排序,使其始终是按相同的顺序处理的。这两种方法都会影响性能,而且人们担心其他还会有一些情况下也会导致出现类似 delayed checkout 这样的乱序操作,从而使这个 bug 死灰复燃。因此最终选择的解决方案是,每次执行删除目录操作时,就会对 cache 进行 invalidate 操作。
如上所述,符号链接在这个过程中起到了帮凶的作用。虽然符号链接非常有用,但历史上它也曾被各种利用来进行破坏。在 race condition exploits(例如临时文件)中就经常利用符号链接。并非所有的系统都支持符号链接,但是 Unix 衍生系统(Linux、macOS)一般都支持。如今,Windows 管理员也可以创建符号链接了。
因此,这几个不同的功能和特殊情况组合在一起,就导致了一个系统漏洞,此外还需要有一个攻击者精心制作的 Git repository,并且用户被欺骗去对其进行 clone 操作。哪怕是对 Windows 系统这种既使用 Git LFS 而且文件系统也不区分大小写的系统,利用这个漏洞的攻击也并没有怎么见到过,也许可能根本不存在。这看起来是通过代码审查或测试发现的问题,随后被报告出来并并迅速修复了,甚至都来不及起一个好听的名字、设计个 logo、或者建个专门的网站。如果真有系统被利用这个漏洞攻破了,那么很可能是因为这些攻击非常具有针对性,并且还没有被发现。
虽然 Linux 原生文件系统通常都会区分大小写,但事实上可以被配置为忽略大小写。不仅如此,Linux 还可能在使用 Windows 和 macOS 的那些忽略大小写的文件系统格式。此外,fix patch 中提供的测试程序还揭示了另一种会导致问题的方式,那就是利用 Unicode normalization。测试程序使用了 "ä" 的两种不同的 Unicode 表示形式(U+0061 U+0308,"\141\314\210",和 U+00e4,"\303\244"),并确保文件不会被写到错误的位置。因此,Linux 系统虽然受该 bug 影响的可能性很小,但也并不可以高枕无忧的。
全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。
长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~