Go中的软件架构-使用govulncheck进行漏洞管理

354 阅读4分钟

漏洞管理包括哪些内容?

Go公司的漏洞管理支持由三个明确的支柱组成。

  1. 数据源,包括。
  2. 漏洞数据库巩固了所有的原始数据源,以及
  3. 工具和集成,包括:。

Vulnerability Management Pillars

漏洞数据库和软件包发现网站

漏洞数据库是由Go安全团队审查和策划的,它与软件包发现网站集成,目前包括一些有用的功能,如。

  • 按时间顺序列出已知的漏洞报告。
  • 搜索报告。
  • 专门的报告登陆页面,例如 GO-2022-0603,以及
  • **我最喜欢的一个!**列出软件包旁边的已知漏洞,包括标准库中的漏洞以及第三方漏洞。

Vulnerability Management Third Party

使用govulncheck检测漏洞

govulncheck是一个新的工具,它使用漏洞数据库来检测你的代码库中的已知问题,它类似于我在文章中提到的工具。 Go中的软件架构。安全 - 依赖关系中所介绍的工具,但有三个最大的不同之处。

  1. govulncheck 支持扫描已经编译好的二进制文件来搜索漏洞。
  2. govulncheck 只有在有漏洞的代码被使用时才报告漏洞,并且
  3. govulncheck 是免费的,并得到Go团队的官方支持。

让我们深入了解一下这个新工具。

安装govulncheck

这篇文章所使用的代码可以在Github上找到

govulncheck 需要Go 1.18,要安装它请运行以下程序。

go install golang.org/x/vuln/cmd/govulncheck@latest

在写这篇文章的时候,还没有标记的版本,但是你仍然应该考虑将其版本化为一个具体的提交,而不是像我在文章中提到的那样使用latest学习Go。版本管理工具.

检测已编译二进制文件中的漏洞

这个功能要求评估的二进制文件必须是用Go 1.18或更高版本编译的,这是我不记得在其他地方看到的功能之一。让我们来看看下面的例子

 1package main
 2
 3import (
 4	"fmt"
 5	"net/url"
 6)
 7
 8func main() {
 9	fmt.Println(url.JoinPath("https://go.dev", "../x"))  // https://go.dev/../x
10	fmt.Println(url.JoinPath("https://go.dev/", "../x")) // https://go.dev/x
11}

上面的例子演示了Go 1.19中引入的GO-2022-0988漏洞,后来在Go 1.19.1中修复。为了编译这两个版本,我们可以使用docker,对于Go 1.19,运行以下命令将编译一个名为go119 的本地二进制。

docker run --rm \
  -v "$PWD":/govulncheck -w /govulncheck \
  -e GOOS=darwin -e GOARCH=amd64 \
  golang:1.19.0-buster go build -o go119 .

而运行下面的命令将创建一个使用Go 1.19.1编译的名为go1191 的二进制文件。

docker run --rm \
  -v "$PWD":/govulncheck -w /govulncheck \
  -e GOOS=darwin -e GOARCH=amd64 \
  golang:1.19.1-buster go build -o go1191 .

使用govulncheck go119 测试第一个二进制文件go119 将报告该漏洞。

Vulnerability Management Standard Library

相反,当通过govulncheck go119 ,使用第二个二进制go1191 ,就不会发现漏洞。

Vulnerability Management Standard Library

这个功能允许追溯评估旧的二进制文件,以确定是否需要立即升级,但是请记住,建议不时地进行定期的Go升级和二进制文件重新编译。

检测对你有实际影响的漏洞

一般来说,漏洞工具会扫描源代码来确定导入的软件包是否包含漏洞,govulncheck ,通过检查我们的代码来评估事实上是否调用了漏洞代码,从而避免了错误的否定和嘈杂的报告。

让我们看看两个例子,它们都是在其go.mod ,报告为GO-2022-0603,导入了一个有漏洞的包。

3go 1.19
4
5require gopkg.in/yaml.v3 v3.0.0

第一个例子包括使用有漏洞的代码

 7func main() {
 8	var t interface{}
 9	yaml.Unmarshal([]byte("0: [:!00 \xef"), &t)
10}

执行govulncheck ./... ,正确地报告了该漏洞。

Vulnerability Management Third Party Affected

第二个例子导入了有漏洞的包**,但没有**调用受影响的函数。

 7func main() {
 8	type T struct {
 9		F int `yaml:"a,omitempty"`
10		B int
11	}
12
13	yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
14}

在这种情况下,执行govulncheck ./... ,正确地报告了漏洞**,但**它表明我们没有使用它,这很重要,因为它可以正确地确定补救措施的优先次序,我们肯定需要更新包,但没有紧急的理由,这就是最大的区别。

Vulnerability Management Third Party Affected

使用go.mod 来确定漏洞的工具不会有这种细微的区别,例如Snyk无论如何都会检测两种情况:使用有漏洞的代码不使用有漏洞的代码

总结

这个新功能对Go生态系统来说是一个非常受欢迎的补充,虽然我不认为这个工具会取代现有的工具,但我相信它会对它们进行补充,我期待着看到在未来的版本中会出现什么。