教程:使用 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/[email protected]
您应该会看到以下输出
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.ac.cn/s/govulncheck-feedback.
Using go1.20.3 and [email protected] 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/[email protected]
Fixed in: golang.org/x/[email protected]
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/[email protected]
Fixed in: golang.org/x/[email protected]
解释输出
*注意:如果您没有使用最新版本的 Go,您可能会看到标准库中的其他漏洞。
我们的代码受一个漏洞 GO-2021-0113 的影响,因为它直接在易受攻击的版本 (v0.3.5) 中调用了 golang.org/x/text/language
的 Parse
函数。
另一个漏洞 GO-2022-1059 存在于 v0.3.5 版本的 golang.org/x/text
模块中。但是,它被报告为“信息性”,因为我们的代码从未(直接或间接)调用过其任何易受攻击的函数。
现在,让我们评估漏洞并确定要采取的措施。
评估漏洞
a. 评估漏洞。
首先,阅读漏洞说明并确定它是否确实适用于您的代码和您的用例。如果您需要更多信息,请访问“更多信息”链接。
根据说明,漏洞 GO-2021-0113 在使用 Parse
处理不受信任的用户输入时可能导致 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/[email protected]
您应该会看到以下输出
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.ac.cn/s/govulncheck-feedback.
Using go1.20.3 and [email protected] 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 扫描您的依赖项,您可以通过识别、优先级排序和解决漏洞来保护您的代码库。