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

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

在本教程中,您將學習如何使用 govulncheck 掃描一個簡單的程式是否存在漏洞。您還將學習如何優先處理和評估漏洞,以便您可以首先專注於修復最重要的漏洞。

要了解有關 govulncheck 的更多資訊,請參閱 govulncheck 文件,以及這篇關於 Go 漏洞管理 的部落格文章。我們也很樂意 聽取您的反饋

先決條件

  • Go。 我們建議使用最新版本的 Go 來學習本教程。(有關安裝說明,請參閱 安裝 Go。)
  • 程式碼編輯器。 任何您擁有的編輯器都可以正常工作。
  • 命令終端。 Go 在 Linux 和 Mac 上的任何終端以及 Windows 上的 PowerShell 或 cmd 中都能很好地工作。

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

  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 存在於 golang.org/x/text 模組的 v0.3.5 版本中。但是,它被報告為“資訊性”,因為我們的程式碼從未(直接或間接)呼叫其任何易受攻擊的函式。

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

評估漏洞

a. 評估漏洞。

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

根據描述,當 Parse 用於處理不受信任的使用者輸入時,漏洞 GO-2021-0113 可能會導致 panic。假設我們希望我們的程式能夠承受不受信任的輸入,並且我們擔心拒絕服務,因此該漏洞可能適用。

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://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 命令掃描您的依賴項,您可以識別、優先處理和解決漏洞,從而保護您的程式碼庫。