新发现的SHA-1碰撞对Git有什么影响?

36

最近,一组研究人员生成了两个具有相同SHA-1哈希值的文件(https://shattered.it/)。

由于Git使用这个哈希值进行内部存储,这种类型的攻击对Git有多大影响?


1
可能是Git中的哈希碰撞的重复问题。 - Tim Biegeleisen
仅供完整性:Linus在这个主题上回答了一些问题此处此处 - ckruczek
1
这里可以找到一些很棒的答案:如果Git上的blob发生SHA-1碰撞,会怎么处理? - dahlbyk
2
@TimBiegeleisen(和点赞者):我认为这不是重复的问题,因为它特别涉及最近发现的单个故意SHA-1碰撞,而不是一般思想的理论讨论。当然,一个好的理论讨论应该包含这个问题,但这需要事后回答,而现有的问题显然过去无法回答。 :-) - torek
这个问题在stackoverflow上不是离题了吗?话题本身似乎很有趣,但不适合在stackoverflow上讨论,不是吗?审核系统说这不是离题,但我认为那不正确。 - bkausbk
2个回答

41

编辑,2017年12月末:Git版本2.16正在逐步获得内部接口,以允许使用不同的哈希值。还有很长的路要走。


短而不尽如人意的答案是,示例文件对Git没有问题,但另外两个经过精心计算的文件可能会有问题。我下载了这两个文件,shattered-1.pdf和shattered-2.pdf,并将它们放入一个新的空仓库中。
macbook$ shasum shattered-*
38762cf7f55934b34d179ae6a4c80cadccbb7f0a  shattered-1.pdf
38762cf7f55934b34d179ae6a4c80cadccbb7f0a  shattered-2.pdf
macbook$ cmp shattered-*
shattered-1.pdf shattered-2.pdf differ: char 193, line 8
macbook$ git init
Initialized empty Git repository in .../tmp/.git/
macbook$ git add shattered-1.pdf 
macbook$ git add shattered-2.pdf 
macbook$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   shattered-1.pdf
    new file:   shattered-2.pdf

即使这两个文件具有相同的SHA-1校验和(并且显示大部分相同,尽管一个具有红色背景,另一个具有蓝色背景),它们会得到不同的Git哈希值:
macbook$ git ls-files --stage
100644 ba9aaa145ccd24ef760cf31c74d8f7ca1a2e47b0 0   shattered-1.pdf
100644 b621eeccd5c7edac9b7dcba35a8d5afd075e24f2 0   shattered-2.pdf

这是两个文件在Git中存储的SHA-1校验和:ba9aa...b621e...,它们都不是38762c...。为什么呢?原因是Git将文件存储为字符串文字blob、一个空格、十进制表示的文件大小和ASCII NUL字节,然后才是文件数据。两个文件的大小完全相同。
macbook$ ls -l shattered-?.pdf
...  422435 Feb 24 00:55 shattered-1.pdf
...  422435 Feb 24 00:55 shattered-2.pdf

因此,两者都以文本字面值 blob 422435\0 为前缀(其中 \0 表示单个字节,类似于 C 或 Python 中的八进制转义字符串)。

也许并不令人惊讶,如果您了解 SHA-1 的计算方式,给两个不同的文件添加相同的前缀,即使在之前产生了 相同的校验和,也会导致它们现在产生 不同的 校验和。

这个结果不足为奇的原因是,如果最终的校验和结果对于每个输入位的位置和值都不是极其敏感的话,那么只需重新排列已知的输入文件中的一些位,就可以轻松制造碰撞。 尽管这两个输入文件在char 193, line 8处有不同的字节,但研究人员通过尝试超过9千亿(short scale)的输入才实现了相同的总和。为了得到这个结果,他们放入了一些在他们控制下影响总和的原始数据块,直到找到产生碰撞的输入对。

通过添加blob头,Git改变了位置,仅发生了一次意外的错位就摧毁了110个GPU年的计算。

现在,知道Git会这样做后,他们可以使用以blob 422435\0开头的输入重复他们的110 GPU年计算(前提是他们的牺牲块没有被推动太多;而实际所需的GPU年计算数量可能会有所不同,因为该过程有点随机)。然后,他们将得到两个不同的文件,这些文件可以去掉blob头。这两个文件现在具有不同的SHA-1校验和,但是当使用git add添加时,两个文件将产生相同的SHA-1校验和。

在这种情况下,第一个添加的文件将“获胜”。 (假设它的名称为shattered-3.pdf。) 一个足够好的Git - 我不确定当前的Git是否如此出色; 请参见Ruben's experiment-based answerHow would Git handle a SHA-1 collision on a blob? - 将注意到git add shattered-4.pdf,试图添加第二个文件,与第一个但不同的shattered-3.pdf相撞,并会警告您并失败git add步骤。 在任何情况下,您都无法将这些文件都添加到单个存储库中。

但首先,必须有人花费更多的时间和金钱来计算新的哈希碰撞。


4
只是想指出,添加一个_新的_文件并不会引起安全问题,但如果替换重要、已受损的存储库中的现有 blob,则会有安全隐患。这将允许在历史的任意点插入后门,即使每个提交/标签都被签名,也不会危及存储库的参考或加密完整性。 - strugee
1
什么?我无法解析你的句子。我在谈论一个恶意行为者用恶意代码替换合法的代码块,而没有人注意到;我不确定你对“无限数量的新‘好代码块’”想要表达什么? - strugee
我想说的是,如果你有一个带有好blob的现有存储库,你实际上不能使用Git命令(包括fetch和push)将其替换为坏的存储库。我想也许你想到的是:“我,邪恶的鲍勃,克隆了好鲍勃的存储库G。然后我制造了与好鲍勃的Y blob相同哈希的坏X blob,并构建了一个全新的存储库B,该存储库使用与G相同的哈希。然后我以某种方式说服你,受害者,克隆我的B而不是好鲍勃的G。”这非常棘手,从多个意义上来说:为什么我要取你的而不是好鲍勃的? - torek
同时,我认为你所说的是:“我,邪恶的鲍勃,通过在大规模克隆仓库E(代表邪恶)中偷偷地设置了一个后门,提前计划了多年。现在好鲍勃无法修复它,因为他无法替换我的历史坏文件!”这是真的:他无法用相同哈希值的文件替换该文件,但他并不需要这样做。没有必要假设存在邪恶行为,因为许多软件中存在大量零日漏洞。 :-) - torek
1
啊,是啊。我原以为规范仓库已经以其他方式被破坏了,比如通过 GitHub 的漏洞。 - strugee
显示剩余2条评论

17
也许Linus的回复可以阐明一些问题:
我记得有人正在对git的SHA1假设进行参数化,因此存储库最终可能会使用更安全的哈希。这个工作进展到了什么程度?在git.git HEAD中仍然有许多“40”常量。
我认为您不一定想改变哈希的大小。您可以使用不同的哈希,只需从其中使用相同的160位。
由于我们现在在有效的PDF文件中具有冲突,因此可能能够构造在有效的git提交和树对象中的冲突。
我还没有看到攻击,但是git实际上并不只是对数据进行哈希,它会在其前面添加类型/长度字段。通常,这使得碰撞攻击更加困难,因为您必须使结果大小也相同,或者您必须能够编辑标题中的大小字段。 pdf没有这个问题,它们有一个固定的标题,您可以在其中相当任意地添加沉默数据,而这些数据只是不显示。
因此,pdf成为更好的攻击向量,正是因为它们是一个相当不透明的数据格式。 Git在某些地方具有不透明数据(例如,我们故意隐藏提交对象中的内容,但按定义,该不透明数据相当次要)。
换句话说:我不认为git作为源控制管理工具已经崩溃。我们想迁移到另一个哈希吗?是的。SHA1像人们所说的那样“游戏结束”了吗?可能不。
我还没有看到攻击细节,但我打赌:
(a)我们有单独的大小编码使得在git对象上进行此操作变得更加困难
(b)我们可能可以轻松地添加一些额外的健全性检查来使我们拥有的不透明数据更加困难,以使其隐藏随机数据这种攻击几乎总是依赖于。
林纳斯

来源:https://marc.info/?l=git&m=148787047422954


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接