はじめに
セキュリティシフトレフト記事第三弾。
前回は、AWS CodeBuildのバッチビルドでDockerfileとコンテナイメージの脆弱性検査についての実施方法をまとめた。
今回は、並行して実施するアプリケーションの脆弱性解析について考察する。
SASTツールについて
SAST(Static Application Security Testing)とは、名前の通りアプリケーションのセキュリティ検査を静的解析で実施することを指す。
基本的にそのアプリケーションの開発言語に従ったテストツールを用いて実施する。
今回は、Golangで例を挙げて解説をするが、代表的な言語では以下のようなSASTツールがあるので、それぞれプロジェクトに合わせて選択をしていただきたい。
なお、記事を執筆している2024年9月時点のトレンドに合わせて記載しており、セキュリティシフトレフトは日々進化しているので、導入時の最新トレンドを確認する方がより効果を高められる。
開発言語 | ソースコード脆弱性解析 | 依存関係脆弱性解析 |
---|---|---|
Java | FindBugs SonarQube |
OWASP Dependency Check |
Golang | securego/gosec(Go Security Checker) | govulncheck |
Python | Bandit | pip-audit |
Javascript/TypeScript | eslint-plugin-security | npm(npm audit) |
AWS CodeBuildでSASTツールを実行する
前回の記事の以下の章で記載した、11_golangci_lint.yml の内容を記載していく。
と言っても、そんなに難しいことはなく、普通にinstallフェーズでSASTツールをインストールして実行すれば良い。
version: 0.2
phases:
install:
runtime-versions:
golang: 1.21
commands:
# install golangci-lint
- VERSION=$(curl --silent "https://api.github.com/repos/golangci/golangci-lint/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
- wget -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh -O - | sh -s -- -b $(go env GOROOT)/bin v${VERSION}
- ln -s $(go env GOROOT)/bin/golangci-lint /root/.goenv/shims/golangci-lint
# install govulncheck
- go install golang.org/x/vuln/cmd/govulncheck@latest
build:
commands:
- cd src_go
- golangci-lint run --timeout=2m --out-format=json --enable=gosec ./... | jq .
- govulncheck --format json ./...
securego/gosec(Go Security Checker)
gosecは、ソースコードに埋め込まれた脆弱性を静的解析で摘出するツールだ。
たとえば、変数にクレデンシャル情報を格納した場合は以下のように指摘をしてくれる。
{
"Issues": [
{
"FromLinter": "gosec",
"Text": "G101: Potential hardcoded credentials",
"Severity": "",
"SourceLines": [
"\tgitlabCredentials := \"glpat-xxxxxxxxxxxxxxxxxxxx\""
],
"Replacement": null,
"Pos": {
"Filename": "main.go",
"Offset": 0,
"Line": 49,
"Column": 2
},
"ExpectNoLint": false,
"ExpectedNoLintLinter": ""
}
]
}
その他のチェックの詳細は公式のGitHubに検査内容が記載されているため確認いただきたい。
今回、gosecを直接実行するのではなく、他にも様々なチェックを同時に実行してくれるgolangci-lintに組み込まれているものを使用して、他の項目もまとめて検査をする。gosecはデフォルトでの検査対象になっていないため、--enable=gosec
で有効化しよう。
基本的にgolangci-lintを使っている場合はプロジェクト単位に細かくチューニングをしていると思われるので、Configファイルでの有効化になると思われる。
--timeout=2m
は、デフォルトが1分で、AWS CodeBuildのスペック次第ではgolangci-lintがタイムアウトしがちなので、適当に延ばしておく。
govulncheck
govulncheckは、Golang公式の脆弱性管理でも利用を推奨されているツールだ。
Go Security Teamが管理しているGo vulnerability databaseとの突き合せを行い、依存関係パッケージの脆弱性検査を行う。
--format json
すると、exitコードが必ず0になってしまうため融通が利きにくいが、govulncheckで検出される脆弱性は「Golangのメジャーバージョンアップ」でしか解消しないものがあり、それはそれでハードルが高いため、検出された内容を確認しながら対処要否を検討することになるだろう。
たとえば、go:1.21で検出される以下の脆弱性について、
Vulnerability #1: GO-2024-3106
Stack exhaustion in Decoder.Decode in encoding/gob
More info: https://pkg.go.dev/vuln/GO-2024-3106
Standard library
Found in: encoding/gob@go1.21.7
Fixed in: encoding/gob@go1.22.7
Example traces found:
#1: main.go:32:14: GoPipeline.main calls lambda.Start, which eventually calls gob.Decoder.Decode
More infoの参照先を確認すると、
Calling Decoder.Decode on a message which contains deeply nested structures can cause a panic due to stack exhaustion. This is a follow-up to CVE-2022-30635.
と書かれていて、Decoder.Decodeに深いネストの構造を食わせなければ問題ないことが分かるため、アプリケーションがそのような作りになっていなければ無視できる、と考えられる。
その他、コンテナビルド前に何をすべきか
実際にプロジェクトで運用する場合は、コンテナビルド前にgo test
を実行してアプリケーションがデグレードしていないことを検査しておこう。
テストについてはセキュリティシフトレフトのコンテキストからは外れるため、本記事では省略するが、GolangにおけるAWS CodeBuildのテストのノウハウは以下の記事でまとめているため、必要に応じて参照いただきたい。
これで、アプリケーションについてもビルド前に安全性を担保できるようになった!