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