最近、研究者のチームが同じSHA-1ハッシュ( https://shattered.it/ )で2つのファイルを生成しました。
Gitはこのハッシュを内部ストレージに使用するので、この種の攻撃はGitにどの程度影響しますか?
編集、2017年12月下旬: Gitバージョン2.16は、さまざまなハッシュに対応するために内部インターフェースを徐々に取得しています 。まだ長い道のりがあります。
短い(しかし満足のいくものではない)答えは、サンプルファイルはGitにとって問題ではないということですが、2つのother(慎重に計算された)ファイルcouldが問題になります。
これらのファイル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
2つのファイルは同じSHA-1チェックサムを持っています(そして、1つは赤い背景でもう1つは青い背景ですが、ほとんど同じように表示されます)が、それらは異なるGitハッシュを取得:
macbook$ git ls-files --stage
100644 ba9aaa145ccd24ef760cf31c74d8f7ca1a2e47b0 0 shattered-1.pdf
100644 b621eeccd5c7edac9b7dcba35a8d5afd075e24f2 0 shattered-2.pdf
これらは、ファイルの2つのSHA-1チェックサムですGitに保存されているとおり:1つはba9aa...
で、もう1つはb621e...
です。どちらも38762c...
ではありません。しかし—なぜ?
答えは、Gitがファイルを格納するのではなく、文字列リテラルblob
、空白、10進数化されたファイルのサイズ、およびASCII NULバイト、およびthenファイルデータ両方のファイルのサイズはまったく同じです:
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
は1バイトを表し、CまたはPython文字列の8進エスケープ)。
SHA-1の計算方法がわかっている場合は、おそらく驚くかもしれませんが、2つの異なるファイルに同じプレフィックスを追加しますが、それでも同じチェックサムを生成すると、 differentチェックサムを生成します。
これが驚くべきことではない理由は、最終的なチェックサム結果がnotpositionおよび各入力ビットの値に非常に敏感である場合、簡単です既知の入力ファイルを取得し、そのビットの一部を再配置するだけで、オンデマンドで衝突を生成します。これらの2つの入力ファイルは、char 193, line 8
に異なるバイトがあるにもかかわらず同じ合計を生成しますが、研究者によると、この結果は9千を超える( short scale )入力を試行することで達成されました。 getの結果として、衝突につながる入力のペアが見つかるまで、合計に影響する、慎重に選択した生データのブロックを、制御した位置に配置しました。
blob
ヘッダーを追加することにより、Git 位置を移動、110 GPU年の計算を1つの多かれ少なかれ偶発的なげっぷで破壊しました。
これで、Gitがこれを実行することがわかっているため、[繰り返しblob 422435\0
で始まる入力を使用して110 GPU年の計算を行うことができます(ただし、犠牲ブロックがあまり押し付けられない場合) ;そして、必要なGPU年の計算の実際の数は、プロセスが少し stochastic )であるため、おそらく異なるでしょう。次に、blob
ヘッダーが削除される可能性のある2つのdifferentファイルが作成されます。これらの2つのファイルは互いに異なるSHA-1チェックサムを持つようになりますが、git add
- edの場合、どちらもsame SHA-1チェックサムを生成します。
その特定のケースでは、追加された最初のファイルがスロットを「獲得」します。 (名前がshattered-3.pdf
であるとしましょう。)十分なGit —現在のGitがこれほど優れているかどうかは、まったくわかりません。 Rubenの実験ベースの回答 を参照 GitはblobでSHA-1の衝突をどのように処理しますか? — 2番目のファイルを追加しようとするgit add shattered-4.pdf
に気付くでしょう、最初とは異なるshattered-3.pdf
と衝突し、警告が表示されてgit add
ステップが失敗します。いずれの場合も、これらのファイルの両方を単一のリポジトリに追加することはできません。
しかし、最初に、誰かが新しいハッシュ衝突を計算するためにより多くの時間とお金を費やす必要があります。
たぶん、Linusの応答はいくつかの光を放つかもしれません:
IIRCの誰かがgitのSHA1仮定のパラメーター化に取り組んでいるため、リポジトリは最終的にはより安全なハッシュを使用できます。それはどこまで進んだのですか? git.git HEADにはまだ多くの「40」定数があります。
必ずしもハッシュのサイズを変更したいとは思わないでしょう。別のハッシュを使用して、同じ160ビットをそのまま使用できます。
有効なPDFファイルで衝突が発生したため、有効なgit commitおよびツリーオブジェクトでの衝突はおそらく構築できます。
私はまだ攻撃を見ていませんが、gitは実際にデータをハッシュするだけではなく、タイプ/長さフィールドを付加します。結果のサイズも同じにするか、ヘッダーのサイズフィールドを編集できるようにする必要があるため、通常は衝突攻撃がはるかに困難になる傾向があります。
pDFにはその問題はありません。固定ヘッダーがあり、表示されないだけのサイレントデータを中央に任意に追加できます。
したがって、pdfはかなり不透明なデータ形式であるため、攻撃ベクトルが大幅に改善されます。 Gitの一部の場所には不透明なデータがあります(たとえば、コミットオブジェクトの物を意図的に非表示にしていますが、定義上、不透明なデータはかなり二次的なものです。
別の言い方をすると、ソースコントロール管理ツールとしてのgitが空に落ちているのではないかと思います。別のハッシュに移行したいですか?はい。人々が言いたいようなSHA1の「ゲームオーバー」ですか?おそらく違います。
攻撃の詳細は見ていませんが、
(a)個別のサイズのエンコーディングを使用しているため、そもそもgitオブジェクトに対して実行するのがはるかに困難です
(b)これらの攻撃がほとんど常に依存するランダムデータの非表示を実行するのをはるかに困難にするために、おそらく簡単に追加の健全性チェックを不透明データに追加できます。
ライナス