• English
  • 使用 govulncheck 尋找並修復易受攻擊的依賴項

    Govulncheck 是一個低噪音工具,幫助你發現並修復 Go 專案中的易受攻擊依賴項。它透過掃描專案的依賴項來查找已知漏洞,然後識別程式碼中對這些漏洞的直接或間接呼叫。

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

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

    先決條件

    • 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://go.dev/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
      由於索引計算錯誤,格式不正確的語言標籤會導致 Parse 因越界讀取而發生恐慌。
      如果 Parse 用於處理不受信任的用戶輸入,這可能用作拒絕服務攻擊的載體。
    
      更多資訊: https://pkg.go.dev/vuln/GO-2021-0113
    
      模組: golang.org/x/text
        發現於: golang.org/x/text@v0.3.5
        修復於: golang.org/x/text@v0.3.7
    
        呼叫堆疊在你的程式碼中:
          main.go:12:29: vuln.tutorial.main 呼叫 golang.org/x/text/language.Parse
    
    === 資訊性漏洞 ===
    
    在你的匯入套件中發現了 1 個漏洞,但沒有呼叫堆疊導致使用此漏洞。你可能不需要採取任何行動。詳情見 https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
    
    漏洞 #1: GO-2022-1059
      攻擊者可以透過建構一個 Accept-Language 標頭來導致拒絕服務,ParseAcceptLanguage 將花費大量時間解析。
      更多資訊: https://pkg.go.dev/vuln/GO-2022-1059
      發現於: golang.org/x/text@v0.3.5
      修復於: golang.org/x/text@v0.3.8

    解釋輸出

    *注意:如果你沒有使用最新版本的 Go,你可能會看到來自標準函式庫的額外漏洞。

    我們的程式碼受到一個漏洞的影響, GO-2021-0113,因為它直接呼叫了 golang.org/x/text/languageParse 函數,且該函數處於易受攻擊的版本(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/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 掃描你的依賴項,你可以透過識別、優先處理和解決漏洞來保護你的程式碼庫。