チュートリアル:govulncheckで脆弱な依存関係を見つけて修正する
Govulncheckは、Goプロジェクトの脆弱な依存関係を見つけて修正するのに役立つ、ノイズの少ないツールです。これは、プロジェクトの依存関係を既知の脆弱性についてスキャンし、コード内のそれらの脆弱性への直接または間接的な呼び出しを識別することで実現します。
このチュートリアルでは、govulncheckを使用して単純なプログラムの脆弱性をスキャンする方法を学びます。また、最も重要な脆弱性の修正に最初に集中できるように、脆弱性の優先順位付けと評価の方法も学びます。
govulncheckの詳細については、govulncheckドキュメント、およびGoの脆弱性管理に関するブログ投稿を参照してください。また、フィードバックをお待ちしております。
前提条件
- Go。 このチュートリアルに従うには、最新バージョンのGoを使用することをお勧めします。(インストール手順については、Goのインストールを参照してください。)
- コードエディター。 お持ちのエディターであればどれでも問題ありません。
- コマンドターミナル。 Goは、LinuxおよびMacの任意のターミナル、およびWindowsのPowerShellまたはcmdでうまく機能します。
このチュートリアルでは、次の手順について説明します。
- 脆弱な依存関係を持つサンプルGoモジュールを作成する
- govulncheckをインストールして実行する
- 脆弱性を評価する
- 脆弱な依存関係をアップグレードする
脆弱な依存関係を持つサンプルGoモジュールを作成する
ステップ1。 まず、vuln-tutorial
という新しいフォルダーを作成し、Goモジュールを初期化します。(Goモジュールを初めて使用する場合は、go.dev/doc/tutorial/create-moduleを確認してください。)
たとえば、ホームディレクトリから、次を実行します。
$ mkdir vuln-tutorial
$ cd vuln-tutorial
$ go mod init vuln.tutorial
ステップ2。 vuln-tutorial
フォルダー内にmain.go
というファイルを作成し、次のコードをコピーします。
package main
import (
"fmt"
"os"
"golang.org/x/text/language"
)
func main() {
for _, arg := range os.Args[1:] {
tag, err := language.Parse(arg)
if err != nil {
fmt.Printf("%s: error: %v\n", arg, err)
} else if tag == language.Und {
fmt.Printf("%s: undefined\n", arg)
} else {
fmt.Printf("%s: tag %s\n", arg, tag)
}
}
}
このサンプルプログラムは、コマンドライン引数として言語タグのリストを受け取り、各タグが正常に解析されたかどうか、タグが未定義であるか、タグの解析中にエラーが発生したかを示すメッセージを出力します。
ステップ3。 go mod tidy
を実行します。これにより、前のステップでmain.go
に追加したコードに必要なすべての依存関係がgo.mod
ファイルに入力されます。
vuln-tutorial
フォルダーから、次を実行します。
$ go mod tidy
次の出力が表示されるはずです。
go: finding module for package golang.org/x/text/language
go: downloading golang.org/x/text v0.9.0
go: found golang.org/x/text/language in golang.org/x/text v0.9.0
ステップ4。 go.mod
ファイルを開いて、次のようになっていることを確認します。
module vuln.tutorial
go 1.20
require golang.org/x/text v0.9.0
ステップ5。 既知の脆弱性を含むgolang.org/x/text
のバージョンをv0.3.5にダウングレードします。次を実行します。
$ go get golang.org/x/text@v0.3.5
次の出力が表示されるはずです。
go: downgraded golang.org/x/text v0.9.0 => v0.3.5
go.mod
ファイルは次のようになります。
module vuln.tutorial
go 1.20
require golang.org/x/text v0.3.5
それでは、govulncheckの動作を見てみましょう。
govulncheckをインストールして実行する
ステップ6。 go install
コマンドでgovulncheckをインストールします。
$ go install golang.org/x/vuln/cmd/govulncheck@latest
ステップ7。 分析するフォルダー(この場合はvuln-tutorial
)から、次を実行します。
$ govulncheck ./...
次の出力が表示されるはずです。
govulncheck is an experimental tool. Share feedback at https://go.dokyumento.jp/s/govulncheck-feedback.
Using go1.20.3 and govulncheck@v0.0.0 with
vulnerability data from https://vuln.go.dev (last modified 2023-04-18 21:32:26 +0000 UTC).
Scanning your code and 46 packages across 1 dependent module for known vulnerabilities...
Your code is affected by 1 vulnerability from 1 module.
Vulnerability #1: GO-2021-0113
Due to improper index calculation, an incorrectly formatted
language tag can cause Parse to panic via an out of bounds read.
If Parse is used to process untrusted user inputs, this may be
used as a vector for a denial of service attack.
More info: https://pkg.go.dev/vuln/GO-2021-0113
Module: golang.org/x/text
Found in: golang.org/x/text@v0.3.5
Fixed in: golang.org/x/text@v0.3.7
Call stacks in your code:
main.go:12:29: vuln.tutorial.main calls golang.org/x/text/language.Parse
=== Informational ===
Found 1 vulnerability in packages that you import, but there are no call
stacks leading to the use of this vulnerability. You may not need to
take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
for details.
Vulnerability #1: GO-2022-1059
An attacker may cause a denial of service by crafting an
Accept-Language header which ParseAcceptLanguage will take
significant time to parse.
More info: https://pkg.go.dev/vuln/GO-2022-1059
Found in: golang.org/x/text@v0.3.5
Fixed in: golang.org/x/text@v0.3.8
出力の解釈
*注:最新バージョンのGoを使用していない場合、標準ライブラリから追加の脆弱性が表示される場合があります。
私たちのコードは、脆弱なバージョン(v0.3.5)でgolang.org/x/text/language
のParse
関数を直接呼び出しているため、1つの脆弱性GO-2021-0113の影響を受けます。
別の脆弱性GO-2022-1059は、v0.3.5のgolang.org/x/text
モジュールに存在します。ただし、コードが脆弱な関数を(直接または間接的に)呼び出すことはないため、「情報提供」として報告されます。
次に、脆弱性を評価し、講じるアクションを決定しましょう。
脆弱性を評価する
a. 脆弱性を評価する。
まず、脆弱性の説明を読み、それが実際にコードとユースケースに適用されるかどうかを判断します。詳細が必要な場合は、「詳細情報」リンクにアクセスしてください。
説明に基づくと、脆弱性GO-2021-0113は、Parse
が信頼できないユーザー入力の処理に使用される場合にパニックを引き起こす可能性があります。プログラムが信頼できない入力に耐えられるようにし、サービス拒否を懸念していると仮定すると、脆弱性が適用される可能性が高くなります。
GO-2022-1059は、コードがそのレポートから脆弱な関数を呼び出さないため、コードに影響を与えない可能性が高くなります。
b. アクションを決定する。
GO-2021-0113を軽減するには、いくつかのオプションがあります。
- オプション1:修正済みバージョンにアップグレードする。 修正が利用可能な場合は、モジュールの修正済みバージョンにアップグレードすることで、脆弱な依存関係を削除できます。
- オプション2:脆弱なシンボルの使用を停止する。 コード内の脆弱な関数へのすべての呼び出しを削除することもできます。代替手段を見つけるか、自分で実装する必要があります。
この場合、修正が利用可能であり、Parse
関数はプログラムに不可欠です。依存関係を「修正済み」バージョンであるv0.3.7にアップグレードしましょう。
情報提供の脆弱性であるGO-2022-1059の修正を後回しにすることにしましたが、GO-2021-0113と同じモジュールにあり、修正済みバージョンがv0.3.8であるため、v0.3.8にアップグレードすることで、両方を同時に簡単に削除できます。
脆弱な依存関係をアップグレードする
幸い、脆弱な依存関係のアップグレードは非常に簡単です。
ステップ8。 golang.org/x/text
をv0.3.8にアップグレードする。
$ go get golang.org/x/text@v0.3.8
次の出力が表示されるはずです。
go: upgraded golang.org/x/text v0.3.5 => v0.3.8
(latest
またはv0.3.8以降の他のバージョンにアップグレードすることもできたことに注意してください)。
ステップ9。 次に、govulncheckを再度実行します。
$ govulncheck ./...
次の出力が表示されます。
govulncheck is an experimental tool. Share feedback at https://go.dokyumento.jp/s/govulncheck-feedback.
Using go1.20.3 and govulncheck@v0.0.0 with
vulnerability data from https://vuln.go.dev (last modified 2023-04-06 19:19:26 +0000 UTC).
Scanning your code and 46 packages across 1 dependent module for known vulnerabilities...
No vulnerabilities found.
最後に、govulncheckは脆弱性が見つからなかったことを確認します。
コマンドgovulncheckを使用して依存関係を定期的にスキャンすることで、脆弱性を特定、優先順位付け、対処することにより、コードベースを保護できます。