安全源代码

1. 概览

安全源代码技术是一组可用于提高源代码安全性的做法。这些技术有助于识别和修复源代码中的漏洞、防止对源代码的未经授权访问,以及保护源代码免遭修改。

一些常见的安全源代码技术包括:

  • Linting:Linting 是指检查源代码是否存在错误和格式问题的过程。这项工作是通过 lint 工具完成的,该工具是一个用于分析源代码并识别潜在问题的程序。lint 工具可用于检查各种错误,包括语法错误、语义错误、样式错误和安全漏洞。
  • 静态应用安全测试 (SAST):SAST 是一种安全测试,用于分析源代码、二进制代码或字节代码,以识别安全漏洞。SAST 工具可用于查找各种编程语言(包括 Go、Java、Python、C++ 和 C#)中的漏洞。
  • 许可扫描:许可扫描是指识别软件应用中使用的第三方软件组件的许可的过程。这一点非常重要,因为这有助于确保应用符合许可条款,从而避免法律问题。

这些技术可用于在软件开发生命周期的所有阶段提高源代码的安全性。lint 可用于在开发过程中尽早发现错误,SAST 可用于在代码编译或部署之前查找漏洞,而许可扫描可用于确保应用符合许可条款。

使用这些技术有助于提高源代码的安全性并降低安全漏洞的风险。

学习内容

本实验将重点介绍用于保护软件源代码的工具和技术。

  • 执行 lint 检查
  • 静态应用安全测试
  • 许可扫描

本实验中使用的所有工具和命令都将在 Cloud Shell 中执行。

2. 设置和要求

自定进度的环境设置

  1. 登录 Google Cloud 控制台,然后创建一个新项目或重复使用现有项目。如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 项目名称是此项目参与者的显示名称。它是 Google API 尚未使用的字符串。您可以随时更新。
  • 项目 ID 在所有 Google Cloud 项目中是唯一的,并且是不可变的(一经设置便无法更改)。Cloud 控制台会自动生成一个唯一字符串;通常情况下,您无需关注该字符串。在大多数 Codelab 中,您都需要引用项目 ID(通常用 PROJECT_ID 标识)。如果您不喜欢生成的 ID,可以再随机生成一个 ID。或者,您也可以尝试自己的项目 ID,看看是否可用。完成此步骤后便无法更改该 ID,并且此 ID 在项目期间会一直保留。
  • 此外,还有第三个值,即部分 API 使用的项目编号,供您参考。如需详细了解所有这三个值,请参阅文档
  1. 接下来,您需要在 Cloud 控制台中启用结算功能,以便使用 Cloud 资源/API。运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。若要关闭资源以避免产生超出本教程范围的结算费用,您可以删除自己创建的资源或删除整个项目。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。

启动 Cloud Shell Editor

本实验室专为与 Google Cloud Shell 编辑器搭配使用而设计和测试。如需访问编辑器,请执行以下操作:

  1. 前往 https://console.cloud.google.com 访问您的 Google 项目。
  2. 点击右上角的 Cloud Shell 编辑器图标

8560cc8d45e8c112.png

  1. 窗口底部会打开一个新窗格
  2. 点击“打开编辑器”按钮

9e504cb98a6a8005.png

  1. 编辑器随即会打开,其中 Explorer 位于右侧,编辑器位于中间区域
  2. 屏幕底部还应显示一个终端窗格
  3. 如果终端未打开,请使用 `ctrl+`` 组合键打开新的终端窗口

环境设置

将 GOPATH 设置为单个目录,以简化本实验中使用的命令。

export GOPATH=$HOME/gopath

创建一个目录来存放我们的工作

mkdir -p workspace
cd workspace

克隆源代码库

git clone https://gitlab.com/gcp-solutions-public/shift-left-security-workshop/source-code-lab.git
cd source-code-lab
export WORKDIR=$(pwd)

3. lint 检查

lint 用于检查与语法相关的常见样式错误或缺陷。lint 通过为多个团队提供通用的语法模式来协助保障安全,从而加快代码审核速度、分享知识并使代码更加清晰。

此外, lint 还会识别可能导致常见漏洞(例如不当或低效使用库或核心 API)的常见语法错误。

安装 staticcheck 关联工具

 go get honnef.co/go/tools/cmd/staticcheck@latest

在项目根目录中运行 Go lint 工具 (staticcheck)

 staticcheck

查看输出

main.go:42:29: unnecessary use of fmt.Sprintf (S1039)

您收到此错误是因为 http.ListenAndServe() 接受字符串,而当前代码使用 Sprintf,而未将变量传递给字符串

查看命令退出状态。

echo $?

在本例中,由于该命令导致了错误,因此退出状态将为 1 或更大。这是可以在 CI/CD 流水线中用于确定工具成功/失败情况的方法之一。

修改 main.go 文件,并修正代码:

  • main() 方法内,通过添加前导斜线(//) 注释掉 LINTING - Step 1 下方的代码行。
  • 移除 main() 方法内 LINTING - Step 2 正下方的两行代码开头的斜线,取消对这两行的注释。

在项目根目录中重新运行 staticcheck

staticcheck

该命令不应返回任何结果(即空行)。

检查命令的退出状态。

  echo $?

在本例中,由于该命令未导致错误,因此退出状态将为 zero

4. 静态应用安全测试

AST/静态安全测试 - 提供静态代码分析,以查找常见的弱点和漏洞 ( CWEs)

安装 AST 工具 (gosec)

    export GOSEC_VERSION="2.15.0"
    curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | \
          sh -s -- -b $(go env GOPATH)/bin v${GOSEC_VERSION}

针对源代码使用政策文件运行 gosec

gosec -conf policies/gosec-policy.json -fmt=json ./...

输出应类似于以下内容

{
    "Golang errors": {},
    "Issues": [
        {
            "severity": "HIGH",
            "confidence": "LOW",
            "cwe": {
                "ID": "798",
                "URL": "https://cwe.mitre.org/data/definitions/798.html"
            },
            "rule_id": "G101",
            "details": "Potential hardcoded credentials",
            "file": "/home/random-user-here/shift-left-security-workshop/labs/source-code-lab/main.go",
            "code": "31: \t// STEP 2: Change this and the reference below to something different (ie, not \"pawsword\" or \"password\")\n32: \tvar pawsword = \"im-a-cute-puppy\"\n33: \tfmt.Println(\"Something a puppy would use: \", username, pawsword)\n",
            "line": "32",
            "column": "6"
        }
    ],
    "Stats": {
        "files": 1,
        "lines": 89,
        "nosec": 0,
        "found": 1
    }
}

该工具发现了一个潜在问题:Potential hardcoded credentials

5. 许可扫描

许可对安全至关重要,因为它们可能会依法要求您公开您可能不想公开的源代码。这种许可称为“copyleft”许可,如果您使用了采用这些许可的依赖项,则需要公开源代码。

安装 golicense

mkdir -p /tmp/golicense
wget -O /tmp/golicense/golicense.tar.gz https://github.com/mitchellh/golicense/releases/download/v0.2.0/golicense_0.2.0_linux_x86_64.tar.gz
pushd /tmp/golicense
tar -xzf golicense.tar.gz
chmod +x golicense
mv golicense $(go env GOPATH)/bin/golicense
popd

构建二进制文件

go build

使用不允许“BSD-3-Clause”许可的当前政策文件运行许可检查

golicense policies/license-policy.hcl hello-world

注意:此操作应会失败,并显示类似的输出:

 🚫 rsc.io/sampler    BSD 3-Clause "New" or "Revised" License
 🚫 rsc.io/quote      BSD 3-Clause "New" or "Revised" License
 🚫 golang.org/x/text BSD 3-Clause "New" or "Revised" License

修改政策文件 policies/license-policy.hcl,将“BSD-3-Clause”从 deny 列表移至 allow 列表。

重新运行许可检查

golicense policies/license-policy.hcl hello-world

注意:此操作应成功完成,并会输出类似的结果:

    ✅ rsc.io/quote      BSD 3-Clause "New" or "Revised" License
    ✅ rsc.io/sampler    BSD 3-Clause "New" or "Revised" License
    ✅ golang.org/x/text BSD 3-Clause "New" or "Revised" License

6. 恭喜

恭喜,您已完成此 Codelab!

您学到了什么

  • 用于保护源代码的工具和技巧

上次更新时间:2023 年 3 月 23 日