Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go Get での checksum 不一致 に遭遇した話とその対応

ANDPAD inc
December 03, 2023

Go Get での checksum 不一致 に遭遇した話とその対応

小島 夏海 @replu5
2023 月 12 月 2 日
Go Conference mini 2023 Winter IN KYOTO
description
本 LT では、 GOPROXY 環境変数や proxy.golang.org の仕様を簡単に紹介し、 go get 時に checksum の不一致に遭遇した時にどうすべきかを実際に遭遇した時の体験談を交えながら紹介します。
ソフトウェア開発の中で利用しているライブラリのアップデート作業は避けられない作業の 1 つです。 Go ではgo getを用いてライブラリのインストールを行いますが、この時 proxy.golang.org に登録されているミラーが実際のコードと異なっていると checksum の不一致が発生します。この事象自体は遭遇頻度が低いため普段意識することはないですが、遭遇した場合は何をすべきなのか迷う方が多いと思います。
本 LT を通じて実施に遭遇した時の行動を共有することで、みなさんが checksum 不一致に遭遇した時の対応の手助けになれば幸いです。

ANDPAD inc

December 03, 2023
Tweet

More Decks by ANDPAD inc

Other Decks in Programming

Transcript

  1. go get時にどういう動作をしているか モジュール配布元 checksum server go get xxx 1 :

    モジュールダウンロード 2 : checksum ダウンロード 3 : 計算したchecksum とダウンロードした checksumと比較 4 : go.modとgo.sum更新
  2. go get時にどういう動作をしているか モジュール配布元 checksum server go get xxx 1 :

    モジュールダウンロード 2 : checksum ダウンロード 3 : 計算したchecksum とダウンロードした checksumと比較 4 : go.modとgo.sum更新
  3. エラーの原因 エラーメッセージに考えられる理由が2つ書かれている • オリジンサーバが上書きされている (The bits may have been replaced

    on the origin server) • ダウンロードが攻撃者に傍受された可能性がある (An attacker may have intercepted the download attempt) オリジンサーバが上書きされているかがわかればよさそう
  4. fileのハッシュを求める open := func(fn string) (io.ReadCloser, error) { return os.Open(fn)

    } filePath := "go.mod" s, err := dirhash.Hash1([]string{filePath}, open) if err != nil { fmt.Println(err.Error()) } fmt.Println(s) https://go.dev/play/p/7aEARvckJjD
  5. directoryのハッシュを求める dir := "[email protected]" prefix := "github.com/replu/[email protected]" s, err :=

    dirhash.HashDir(dir, prefix, dirhash.DefaultHash) if err != nil { fmt.Println(err.Error()) } fmt.Println(s) https://go.dev/play/p/UofHVjffeuy
  6. checksumが一致しないことが確認できたら • checksum serverのchecksumは更新できない ◦ そのバージョンは利用しないようにする ▪ GONOSUMDB を指定することで checksum

    の確認をしない ようにできるが、攻撃を受けた時に気付けないのでおすすめは しない ◦ 開発者に連絡して、新バージョンをリリースしてもらう ▪ そのライブラリを利用している他ライブラリが新バージョンを 使っていないなら、そちらも更新してもらう必要がある 自分の場合は新バージョンがでていたが、他ライブラリが 新バージョンを使ってなかったので、そちらにissueを作成して連絡 した
  7. go get時の動作(再喝) モジュール配布元 checksum server go get xxx 1 :

    モジュールダウンロード 2 : checksum ダウンロード 3 : 計算したchecksum とダウンロードした checksumと比較 4 : go.modとgo.sum更新
  8. go get時の動作(再喝) モジュール配布元 checksum server go get xxx 1 :

    モジュールダウンロード 2 : checksum ダウンロード 3 : 計算したchecksum とダウンロードした checksumと比較 4 : go.modとgo.sum更新 この2つの仕様の違いが原因
  9. ダウンロード元とchecksum serverの指定 • GOPROXY ◦ モジュールのダウンロード元を指定する ◦ デフォルトだと proxy.golang.org,direct ▪

    directを指定した場合は直接アクセスになる ▪ カンマ区切りまたはパイプ区切りで指定し、前のものから 使用される • GOSUBDB ◦ checksum serverを指定する ▪ デフォルトではsum.golang.org ◦ offを指定した場合は検証を無効化できる
  10. proxy.golang.orgとsum.golang.org • proxy.golang.org ◦ 明示的にキャッシュを削除することはできない ▪ 無限に保存されるわけではなく適切なライセンスを 検出できない場合などは一定時間でキャッシュが削除される • sum.golang.org

    ◦ 一度記録されたら更新・削除されることはない sum.golang.orgに記録された後にオリジンサーバが上書き された場合、proxy.golang.orgのキャッシュが更新される or directでアクセスしているとchecksumが不一致になる
  11. 参考文献 • Go Module Mirror, Index, and Checksum Database :

    https://sum.golang.org/ • Go Modules Reference : https://go.dev/ref/mod