教程:使用 govulncheck 查詢和修復易受攻擊的依賴項

Govulncheck 是一種低噪音工具,可幫助您在 Go 專案中查詢和修復易受攻擊的依賴項。它透過掃描專案依賴項以查詢已知的漏洞,然後識別程式碼中對這些漏洞的任何直接或間接呼叫來實現此目的。

在本教程中,您將學習如何使用 govulncheck 掃描簡單的程式以查詢漏洞。您還將學習如何對漏洞進行優先順序排序和評估,以便您可以首先專注於修復最重要的漏洞。

要了解有關 govulncheck 的更多資訊,請參閱 govulncheck 文件,以及 Go 的 關於漏洞管理的博文。我們也希望 收到您的反饋

先決條件

本教程將引導您完成以下步驟

  1. 建立一個包含易受攻擊依賴項的示例 Go 模組
  2. 安裝並執行 govulncheck
  3. 評估漏洞
  4. 升級易受攻擊的依賴項

建立一個包含易受攻擊依賴項的示例 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://golang.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 的影響,因為它直接在易受攻擊的版本 (v0.3.5) 中呼叫了 golang.org/x/text/languageParse 函式。

另一個漏洞 GO-2022-1059 存在於 v0.3.5 版本的 golang.org/x/text 模組中。但是,它被報告為“資訊性”,因為我們的程式碼從未(直接或間接)呼叫過其任何易受攻擊的函式。

現在,讓我們評估漏洞並確定要採取的措施。

評估漏洞

a. 評估漏洞。

首先,閱讀漏洞說明並確定它是否確實適用於您的程式碼和您的用例。如果您需要更多資訊,請訪問“更多資訊”連結。

根據說明,漏洞 GO-2021-0113 在使用 Parse 處理不受信任的使用者輸入時可能導致 panic。假設我們的程式旨在抵禦不受信任的輸入,並且我們擔心拒絕服務,因此該漏洞可能適用。

GO-2022-1059 可能不會影響我們的程式碼,因為我們的程式碼沒有呼叫該報告中任何易受攻擊的函式。

b. 確定行動方案。

為了緩解 GO-2021-0113,我們有一些選擇

在本例中,有一個可用的修復程式,並且 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://golang.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 掃描您的依賴項,您可以透過識別、優先順序排序和解決漏洞來保護您的程式碼庫。