Mac
Git
homebrew

macOSのgitをXcode Command Line Tools版からHomebrew版に乗り換えてみた

最近ようやく内定もらえました、306sanです。

さて、先日Gitに関する脆弱性が見つかりました。

プロではないので細かい説明は省きますが、clone時に任意のコードが実行できるというものです。
脆弱性をつかったサンプルがあるので紹介します。
https://github.com/greymd/CVE-2017-1000117
うーん。恐ろしいですね
(個人的には普段はrecursiveオプション使っていないので日常的な恐ろしさを感じていない)

対策済みのバージョンはこちらで確認できます。
https://www.facebook.com/soudai.sone/posts/1528779273844846?comment_id=1529241370465303

現状確認

さて、みなさんはGitをどうやって入れましたか?
確か初めてターミナルを開いたときにgitと入力したら、
gitは入ってないからXcode Command Line Toolsをインストールしてね(意訳)
みたいな英文が出てインストールしたような気がします。

それではバージョンを見てみましょう

git --version                                                                             
git version 2.11.0 (Apple Git-81)

残念ながら、未対策のバージョンのようです。
試しにサンプルコードをcloneしてみます。

git clone --recursive https://github.com/greymd/CVE-2017-1000117.git
Cloning into 'CVE-2017-1000117'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 8 (delta 1), reused 7 (delta 0), pack-reused 0
Unpacking objects: 100% (8/8), done.
Submodule 'subs/morimori' (ssh://-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh /sub1) registered for path 'subs/morimori'
Cloning into '/private/tmp/CVE-2017-1000117/subs/morimori'...
Pseudo-terminal will not be allocated because stdin is not a terminal.
    "mm
    mmmm          "m           "mmmmm
  ""    #         m"               "
        #        m#m          m
       #        m"  #   m     "m     m
     m"        m"   "mm"        """""
   m            m   m          m            m   m
  mm#            # # "m       mm#            # # "m
   m"#"          ##   #        m"#"          ##   #
 ""#mm "m        #    #      ""#mm "m        #    #
   #    #            #         #    #            #
    "mm"           m"           "mm"           m"
ssh_exchange_identification: Connection closed by remote host
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: clone of 'ssh://-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh /sub1' into submodule path '/private/tmp/CVE-2017-1000117/subs/morimori' failed
Failed to clone 'subs/morimori'. Retry scheduled
Cloning into '/private/tmp/CVE-2017-1000117/subs/morimori'...
Pseudo-terminal will not be allocated because stdin is not a terminal.
    "mm
    mmmm          "m           "mmmmm
  ""    #         m"               "
        #        m#m          m
       #        m"  #   m     "m     m
     m"        m"   "mm"        """""
   m            m   m          m            m   m
  mm#            # # "m       mm#            # # "m
   m"#"          ##   #        m"#"          ##   #
 ""#mm "m        #    #      ""#mm "m        #    #
   #    #            #         #    #            #
    "mm"           m"           "mm"           m"
ssh_exchange_identification: Connection closed by remote host
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: clone of 'ssh://-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh /sub1' into submodule path '/private/tmp/CVE-2017-1000117/subs/morimori' failed
Failed to clone 'subs/morimori' a second time, aborting

でていますね。
さて、対策済みのやつにバージョンアップしなくてはと思ったとき、疑問に思いました。
これ、どうやって、アップデートすればいいんだと。
AppStoreから降ってくるんでしょうか。しかし、現時点(2017/08/15)では来ていません。

対策

gitは日常的に使うものなのでとりあえずHomebrewからgitを上書きするような形でインストールしてみました。

brew install git                                                          
==> Downloading https://homebrew.bintray.com/bottles/git-2.14.1.sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring git-2.14.1.sierra.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions

Emacs Lisp files have been installed to:
  /usr/local/share/emacs/site-lisp/git
==> Summary
🍺  /usr/local/Cellar/git/2.14.1: 1,485 files, 33.5MB

よしよし、対策済みのバージョンがインストールされたようです。
それではバージョンを見てみましょう。

git --version                                                                             
git version 2.11.0 (Apple Git-81)

あれれ。おかしいぞ。
brewでインストールしたのに反映されていないぞ。
賢い皆様ならおわかりでしょう。

which git                                                                                    
/usr/bin/git

そうです。PATHの優先順位の問題です。
PATHっていうのは分かりやすく言うとコマンドが入力されたときに見るフォルダーの並び順みたいなものです。
例えば、今だとgitと入力したら、/usr/bin/の中にgitの実行ファイルがないかまず覗きに行きます。
該当するものがなかったら次に指定されたフォルダを覗きに行きます。
今回brewで入れたものは/usr/local/binに入っています。
つまり/usr/local/binを先に覗くように優先順位を上げてやればいいのです。
そんなわけで、.bashrcなり、.zshrcなりに、

export PATH=/usr/local/bin:$PATH

もしくは、config.fishに

set -x PATH /usr/local/bin $PATH

と書き加えるか修正しましょう。

そんでもって再読込させれば、

git --version
git version 2.14.1

良さそうですね。

サンプルも試してみます

git clone --recursive https://github.com/greymd/CVE-2017-1000117.git
Cloning into 'CVE-2017-1000117'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 8 (delta 1), reused 7 (delta 0), pack-reused 0
Unpacking objects: 100% (8/8), done.
Submodule 'subs/morimori' (ssh://-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh /sub1) registered for path 'subs/morimori'
Cloning into '/private/tmp/CVE-2017-1000117/subs/morimori'...
fatal: strange hostname '-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh ' blocked
fatal: clone of 'ssh://-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh /sub1' into submodule path '/private/tmp/CVE-2017-1000117/subs/morimori' failed
Failed to clone 'subs/morimori'. Retry scheduled
Cloning into '/private/tmp/CVE-2017-1000117/subs/morimori'...
fatal: strange hostname '-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh ' blocked
fatal: clone of 'ssh://-oProxyCommand=echo ZWNobyBINHNJQURuTmtWa0FBNFdSVVE3QUlBaEQvemtGS2Vmci9YK0hMc0dpY1hPSmNiNWFzTHE3Zy9UL1lXTWlWUXM5QnhaTUtUQVdVWlRZN0NDdVRjb1FWeTFnaHhMdkQ3VVpMdW1xT1ZmWllHMWdqSEp0MTJmZnVESWJhWVRTeUs4aXViTlpFU0dCUlBSclhaaGwyNUVScjlqRDE4RVBacHRVQklkTll6Tkh6YzIzbDd3eGV3Qy96SHMvV0FJQUFBPT18YmFzZTY0IC0tZGVjb2RlfGd6aXAgLWQgPiAvZGV2L3R0eQo= | base64 --decode | sh /sub1' into submodule path '/private/tmp/CVE-2017-1000117/subs/morimori' failed
Failed to clone 'subs/morimori' a second time, aborting

大丈夫ですね

終わりに

単純にgit使いたいためにXcode Command Line Tools入れてしまったので、結構めんどくさい事にになってしまいました。
Appleさんは早くパッチをリリースしてほしいものです。
アプリ開発はしていないのでXcode Command Line Toolsをアンインストールしても良かったのですが結構いろんなもの(gcc,perlとか)が入ってそれらを消してしまうと悪影響が出てきそうで怖かったのでやめました。
今度クリーンインストールした際は、全てのツールをbrew経由で入れていこうと思います。