web-dev-qa-db-ja.com

git commit hash(sha1)はどの程度安全ですか?

次のシナリオを検討してください。

誰かがgitの適切なバージョンを使用して、git cloneの後にgit checkout一部のコミットハッシュ(40文字の16進数)。

明確にするために、ボブが安全なマシンで次のことを行うと仮定します。

$ git clone https://secureserver.com/HonestEve/project.git
$ git rev-parse HEAD

印刷する

5b3469eccbd7849d760f63af8537940c97c1d1bf

ボブはチェックアウトしたばかりのコードを調べて、それが本当に彼が望んでいる/必要としているものであることを確認します。

その後、後日、ボブは別の安全なマシン(または少なくとも空のディレクトリ)で次のように実行します。

git clone https://malicious.server.com/HonestEve/project.git

またはおそらく同じURLを使用しますが、どういうわけか悪意のあるgitサーバーに接続されます。そして次に進みます:

git checkout 5b3469eccbd7849d760f63af8537940c97c1d1bf

次に、問題は、結果のソースツリーが最初に取得したものと異なる可能性がある(SHA1の衝突または弱点を無視して)かどうかです。

ここで、Bobが使用するgitクライアントは、ほとんどのオペレーティングシステムに付属している、最も広く普及している通常のgitクライアントであると想定できます。最近のバージョン。このgitクライアントの機能を考えると、攻撃者はこのチェックアウトに悪意のあるコードを挿入することができますか?次のことを前提としています。

1)衝突の可能性はありません(まったく同じ入力でSHA1はのみ取得できます)。
2)攻撃者は被害者のgitクライアントを自分の悪意のあるサーバーに接続させることができ、サーバーを完全に制御できますが、クライアントまたはクライアントが実行されているマシンでは制御できません。
3)攻撃者は、被害者が(遠くに)使用するコミットハッシュを知っています。

私が正しい場合、クライアントが元の入力からローカルでsha1を再計算して、結果のチェックアウトが予期したものであることを確認するときに、攻撃者はこれを行うことができません。しかし、それは非常に非効率的です。 sha1のサイズは非常に大きいですが、偶然の衝突を回避することのみを目的としています(?)。

確かにgit checkout <sha1>は、再計算なしで、指定されたsha1の下にリストされているものをすべてチェックアウトします(?)。しかし、おそらくクライアントはクローン/フェッチ中にsha1の正当性を検証しますか?もしそうなら、それはパラノイアであり、上記のような悪意のある攻撃を阻止する明確な努力でしょう。 gitがこれを行うかどうかはわかりません。

誰かがこれに光を当てることができますか?

2
Carlo Wood

ボブはチェックアウトしたばかりのコードを調べ、それが本当に望んでいる/必要としているコードであることを確認します。

その後、後日、ボブは別の安全なマシン(または少なくとも空のディレクトリ)で次のように実行します。

git clone https://malicious.server.com/HonestEve/project.git

またはおそらく同じURLを使用しますが、どういうわけか悪意のあるgitサーバーに接続されます。そして次に進みます:

git checkout 5b3469eccbd7849d760f63af8537940c97c1d1bf

それから問題は、結果のソースツリーが彼が最初に得たものと異なる可能性がある(SHA1の衝突または弱点を無視して)かどうかです。

はい、可能です。これは安全ではありません。

Mallory(malicious.server.comの所有者)は、コード/リポジトリを任意に変更して、5b3469eccbd7849d760f63af8537940c97c1d1bfという名前のブランチを作成できます。

ボブがgit checkout 5b3469eccbd7849d760f63af8537940c97c1d1bfを実行すると、gitrefがあいまいであるという警告を表示しますが、最終的にはコミットよりもブランチを優先します。 (これがビルドスクリプトなどで実行される場合、警告を見逃す可能性があります)

私はこれをgit 2.25.1(Ubuntu 20.04)でテストしました。

このようなブランチをGitHubにプッシュすることもテストしましたが、失敗しました。 GitHubには、ブランチ/タグに40桁の16進文字の名前を付けることができないようにするカスタムチェックがあるようです。

[...]
remote: error: GH002: Sorry, branch or tag names consisting of 40 hex characters are not allowed.
remote: error: Invalid branch or tag name [...]

ただし、このチェックはGitHubに固有のものです。 GitHubから引き出すことでさえ、gitだけでなくGitHubも信頼する必要があることに注意してください。

この特定の攻撃方法の解決策は、必要な参照がコミットハッシュであることをgitに伝えることです。

git checkout 5b3469eccbd7849d760f63af8537940c97c1d1bf^{commit}
3
ghost43