Go 1.19.2 and 1.18.7 security fix の内容を読んだ
https://groups.google.com/g/golang-announce/c/xtuG5faxtaU
3つの security fix が含まれている。
- archive/tar : ヘッダー読み込み時のメモリ消費量に制限をかけた
- net/http/httputil : ReverseProxy でパース不可能なクエリパラメータを転送しないようにした
- regexp/syntax : 正規表現をパースする際のメモリ使用量の制限をかけた
archive/tar : ヘッダー読み込み時のメモリ消費量に制限をかけた
Issue https://github.com/golang/go/issues/54853
Reader.Read はファイルヘッダの最大サイズに制限を設けていなかった。悪意をもって作られたアーカイブは Read に無制限のメモリを割り当て、リソースの枯渇やパニックを引き起こす可能性があった。
Reader.Read はヘッダーブロックの最大サイズを 1MiB に制限するようになった。1MiB は libarchive の仕様に合わせている。
コードを見ると、1MiB を maxSpecialFileSize = 1 << 20
と定義している。 <<
は Arithmetic operators (算術演算子) の中の left shift と呼ばれる。左シフトは、左辺の値を右辺の値だけ左へシフトする(例 0001
=> 0010
)。MiB はメビ・バイトという単位。コンピューターの容量や記憶装置の大きさを表す単位のひとつとして利用される。。MB(メガバイト)は10の6乗バイト(1MB = 100万B)となるが、1MiB は2の20乗バイト(1MiB = 104万8576B)となる。
net/http/httputil : ReverseProxy でパース不可能なクエリパラメータを転送しないようにした
issue https://github.com/golang/go/issues/54663
ReverseProxy でリクエストを転送するときに、パースできないクエリパラメータも含まれていた。クエリパラメータの密輸が可能ということが脆弱性なのかセキュリティ強化策なのかは微妙なところだが、CVE を割り当て脆弱性として扱うことにした。
下位互換性を保ちつつ修正する方法として、条件付きでパースできないクエリパラメータを削除するようにした。
regexp/syntax : 正規表現をパースする際のメモリ使用量の制限をかけた
issue https://github.com/golang/go/issues/55949
解析される各正規表現は 256MB のメモリフットプリントに制限されるようになり、ネストが深い正規表現などそれ以上の容量を必要とする正規表現が拒否されるようになった。
この修正ではサイズが大きすぎる正規表現に対して syntax.ErrInternalError を返すようにしたが、Go 1.20 でこのエラーを変えるプロポーザルが出されていた。すでに Go 1.19 ではこのケースに利用できそうな syntax.ErrNestingEpth が追加されている。