在我们的备忘单系列中,我们将为 Go 开发者介绍八项有关于 Go 安全的最佳实践。Go 语言集成了许多内置特性,这些功能(与 C 等较早和较低级别的语言相比)比如 -- 内存垃圾回收和强类型指针,可以促进更安全的开发实践。
这些功能使得开发人员不需要自行管理内存,从而避免了一些可能被利用的漏洞。然而,开发人员仍需了解一些安全最佳实践。在 Dan Enman(Snyk的高级软件工程师)的帮助下,由 Eric Smalling 和 Gerred Dillon 撰写的这份备忘单,涉及到其中的一些更常见的主题。
- 使用 Go Modules
- 扫描 CVE 之间的依赖关系
- 使用 Go 标准加密软件包
- 使用 html/template 来避免 XSS 攻击
- shell 子进程
- 避免使用 unsafe 和 cgo 特性
- 谨慎使用反射
- 最小化容器攻击面
1.使用 Go Modules
go.sum
go mod init [namespace/project-name]
go.modgo buildtest,install
go.mod
go.sumgo.modgo.sum
可以在 Go 的官方博客上找到关于 Using Go Modules 的教程,这是学习更多有关于 Go Modules 的极好资源,包括学习如何指定依赖版本,清理未使用的依赖等等。
2.扫描 CVE 之间的依赖关系
与大多数项目一样,您的应用程序所依赖的模块中的代码量通常会超过应用程序本身的代码量,而依赖的这些第三方库通常是引入安全漏洞的一个途径。借助 Snyk 这类的工具, 一款由我们提供的通用漏洞数据库,可以测试这些依赖关系图中的已知漏洞,建议进行升级以修复所发现的问题,甚至以持续监视您的项目中是否存在将来发现的任何新漏洞。
synk test
3.使用 Go 标准加密软件包而不是第三方所提供的
Go 标准库加密程序包已经过安全研究人员的严格审核,但由于它们提供的功能并不全面,因此您可能会想使用第三方程序包。
就像不使用自己的加密算法一样,您应该非常警惕第三方加密库,因为它们可能会或可能不会受到相同级别的审核。您应该需要清楚地知道您的应用程序所依赖包的来源。
4.使用 html/template 来避免 XSS 攻击
io.WriteString()text/templateContent-Type: plain/text
html/template
5.shell 子进程
在 Go 中,shell 子进程基本上可以直接对您的系统进行访问,并且这种方式通常仅限于命令行工具类型的应用程序。在可能的情况下,始终希望使用适当的模块在 Go 代码中本地实现(译者注:尽量使用 go 代码实现, 而不是依赖于调用系统外部命令)。
如果您确实需要使用 shell 子进程,请务必清理可能传递给 shell 的任何外部来源数据以及返回的数据,以确保您的应用程序不会暴露有关基础系统的不必要的详细信息(译者注:就是不要对外暴露操作系统的基本信息)。这种考虑类似于要注意模板渲染攻击(请参阅上面的#4)或者 SQL 命令注入。还应考虑将调用运行外部流程作为应用程序请求线程的一部分进行操作可能会产生其他副作用,这些副作用是您无法从 Go 代码中控制的,例如对文件系统的更改,对外部依赖项的调用或对安全格局的更改 可能会阻止此类调用-例如,由在容器中运行或由 AppArmor,SELinux 等工具施加的限制
6.谨慎使用 unsafe 和 cgo
void *unsafeunsafe
cgocgoCGO_ENABLED = 0cgocgo
7.反射
reflect
尽管反射很有用,但也增加了在 Go 代码中运行时引入错误的风险。如果您尝试以错误的方式修改被反射的变量(例如,设置无法在结构上设置的值),则代码会引发 panic。很难很好地掌握代码流以及所反映的各种类型和值类型。最后,在使用反射类型或值时,您可能需要断言这可能会使代码混淆的类型,并导致运行时错误。
尽管反射功能很强大,但是在 Go 的类型和接口系统中,应很少使用它,因为它很容易引发意想不到的问题。
8. 最大限度地减小容器攻击面
许多 Go 应用程序没有外部依赖关系,并且设计为可以在容器中运行,因此我们应该使用几种镜像构建技术来简化对它们可用的文件系统。最简单的方法之一是使用多阶段 Dockerfile,在该阶段我们在构建阶段构建应用程序,然后将临时基础镜像用于部署工件镜像。
看一下以下 Dockerfile 示例:
如果您是 Dockerfile 的新手,那么它们是逐步的说明,几乎所有 OCI 镜像构建都可以使用它们来构建镜像。它们记录在这里。此示例是一个多阶段 Dockerfile,具有两个不同的阶段:构建阶段和最终的运行时镜像阶段
阶段1,第1-12行:构建阶段
golang:1.15
您可能想知道我们传递到构建中的所有环境 var 和参数是什么:
GOPATH=””golang:1.15CGO_ENABLED=0cgoCGO_ENABLED=0cgoGOOS=linuxGOOS=linuxGOARCH=amd66amd64-trimpathldflag -sldflag -w
该设置集合将构建几乎所有可能的最小二进制文件,但是其中一些可能不适用于您的应用程序,因此请根据需要进行选择。
第2阶段,第13-10行:运行时镜像阶段
/etc/passwdbuild
要构建此镜像,我们只需在与Dockerfile相同的目录中运行以下命令:
.
.
mobyshps
Go实战教程: