使用 govulncheck 查找并修复易受攻击的依赖项
Govulncheck 是一个低噪音工具,帮助你发现并修复 Go 项目中的易受攻击依赖项。它通过扫描项目的依赖项来查找已知漏洞,然后识别代码中对这些漏洞的直接或间接调用。
在本教程中,你将学习如何使用 govulncheck 扫描简单程序的漏洞。你还将学习如何优先处理和评估漏洞,以便首先专注于修复最重要的漏洞。
要了解有关 govulncheck 的更多信息,请参阅 govulncheck 文档,以及这篇关于漏洞管理的 博客文章。我们也乐于 听取你的反馈。
先决条件
- 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.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/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/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 扫描你的依赖项,你可以通过识别、优先处理和解决漏洞来保护你的代码库。