教學:使用 govulncheck 尋找並修正有漏洞的相依性
Govulncheck 是一款低噪音工具,可協助您在 Go 專案中找出並修正有漏洞的相依性。它會掃描專案的相依性,找出已知的漏洞,然後識別程式碼中對這些漏洞的任何直接或間接呼叫。
在本教學課程中,您將學習如何使用 govulncheck 掃描簡單程式中的漏洞。您還將學習如何優先處理和評估漏洞,以便您可以專注於優先修正最重要的漏洞。
如需進一步了解 govulncheck,請參閱 govulncheck 文件,以及這篇關於 Go 漏洞管理的 部落格文章。我們也樂於 聽取您的意見回饋。
先決條件
- Go 1.18 或更新版本。Govulncheck 設計為與 Go 1.18 及更新版本搭配使用。(如需安裝說明,請參閱 安裝 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.dev.org.tw/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,您可能會看到標準函式庫中的其他漏洞。
我們的程式碼受到一個漏洞影響,GO-2021-0113,因為它直接呼叫 `golang.org/x/text/language` 的 `Parse` 函式,且版本為有漏洞的版本 (v0.3.5)。
另一個漏洞,GO-2022-1059,存在於 `golang.org/x/text` 模組的 v0.3.5 中。然而,它被報告為「資訊性」,因為我們的程式碼從未(直接或間接)呼叫任何有漏洞的函式。
現在,讓我們評估漏洞並決定採取的行動。
評估漏洞
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.dev.org.tw/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 指令掃描您的依賴項,您可以透過識別、優先處理和解決漏洞來保護您的程式碼庫。