はじめに
Gitlabの機能としてセキュリティツールがいくつかあるので、試したときのメモ
やること
Gitlab.com環境でSASTのうちSemgrepをWebGoatに対してかけてみます。
環境
- Gitlab.com: 14.5.0-pre (2021年10月25日現在)
- Semgrep analyzer: v2.13.3
- WebGoat: https://github.com/WebGoat/WebGoat
やったこと
Gitlabのセットアップ
- Gitlab.com にアクセス
- グループを作成(手順は省略)
- 「Settings」⇨ 「Billing」でGitlab Ultimateの無料トライアルへ切り替え(あとでSASTの結果をGitlab上で確認するため)。
- WebGoatからプロジェクトをインポートする形で新規プロジェクト作成(手順は省略)
gitlab-ci.ymlを作成
結果的に以下のコードで実行を確認。
stages:
- build
- build-docker
- test
variables:
DOCKER_IMAGE: ${CI_REGISTRY}/dyamaguc-testgroup-03/webgoat:${CI_COMMIT_SHORT_SHA}
SECURE_LOG_LEVEL: "debug"
build:
stage: build
image: 'maven:3.8.1-openjdk-15'
variables:
DOCKER_TLS_CERTDIR: ''
services:
- name: 'docker:20.10.6-dind'
script:
- mvn clean install -DskipTests=true -Dmaven.repo.local=./.m2/repository
artifacts:
paths:
- docker/target
- webgoat-server/target
- .m2/
build-docker:
stage: build-docker
image: 'docker:19.03.0'
variables:
DOCKER_DRIVER: overlay
DOCKER_TLS_CERTDIR: ""
services:
- name: 'docker:20.10.6-dind'
dependencies:
- build
before_script:
- docker info
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- cd docker
- docker build -t ${DOCKER_IMAGE} .
- docker push ${DOCKER_IMAGE}
include:
- template: Security/SAST.gitlab-ci.yml
(中略)
semgrep-sast:
dependencies:
- build
before_script:
- touch trigger.py
artifacts:
reports:
sast: gl-sast-report.json
paths:
- gl-sast-report.json
パイプライン実行
パイプラインの実行結果
semgrep-sastジョブの実行結果
ちゃんとスキャンして、Job succeededとなっています。
gl-sast-report.jsonの内容(抜粋)
スキャンの結果がjson形式で出力されるので、試しに確認。それっぽいものが検知されていそうです。
{
"version": "14.0.0",
"vulnerabilities": [
{
"id": "4cd83477f9e3439c6fd7a52bac52b66adfb039278a371bec91bae1dc6e82547f",
"category": "sast",
"message": "Improper Control of Generation of Code ('Code Injection')",
"description": "Bracket object notation with user input is present, this might allow an attacker to access all properties of the object and even it's prototype, leading to possible code execution.",
"cve": "",
"severity": "Medium",
"scanner": {
"id": "semgrep",
"name": "Semgrep"
},
"location": {
"file": "webgoat-container/src/main/resources/static/js/goatApp/controller/LessonController.js",
"start_line": 127,
"end_line": 127
},
"identifiers": [
{
"type": "semgrep_id",
"name": "eslint.detect-object-injection",
"value": "eslint.detect-object-injection",
"url": "https://semgrep.dev/r/gitlab.eslint.detect-object-injection"
},
{
"type": "cwe",
"name": "CWE-94",
"value": "94",
"url": "https://cwe.mitre.org/data/definitions/94.html"
},
{
"type": "eslint_rule_id",
"name": "ESLint rule ID security/detect-object-injection",
"value": "security/detect-object-injection"
}
]
},
...(省略)
Vulnerability Report
試しに1つクリックすると、jsonのレポートの中身がブラウザで確認できます。
レポートに対してIssueを切れるのはいいなーと思いました。
実行する上での注意点
上記gitlab-ci.yml
の中で、before_script
のtouch trigger.py
がポイントです。
Gitlabが提供しているSemgrepのanalyzerのmain.go
の中で以下のようにコマンドが定義されています。
app.Commands = command.NewCommands(command.Config{
Match: plugin.Match,
Analyze: analyze,
AnalyzeFlags: analyzeFlags(),
AnalyzeAll: true,
Convert: convert,
Scanner: metadata.ReportScanner,
ScanType: metadata.Type,
})
このうち、plugin.Match
の中身が
// Match checks if the file extension is .py
func Match(path string, info os.FileInfo) (bool, error) {
ext := filepath.Ext(info.Name())
if ext == ".py" || ext == ".js" || ext == ".ts" ||
ext == ".jsx" || ext == ".tsx" || ext == ".c" || ext == ".go" {
return true, nil
}
return false, nil
}
このように定義されていて、現時点ではリポジトリ直下にスキャン対象の拡張子を持つファイルがないと、semgrepが実行されないようです。
試しにgitlab-ci.yml
のbefore_script
を無くしてパイプラインを回した時のジョブのログが下になります。
ジョブ自体はJob succeededとなるのですが、
[WARN] [Semgrep] [2021-10-26T08:09:02Z] ▶ No match in /builds/dyamaguc-testgroup-03/WebGoat
と表示されていて、実際にはSemgrepが実行されておらず、結果的にレポートのgl-sast-report.json
が出力されていない旨のERRORが表示されています。
ジョブがSucceedになるので、まぎらわしいです...
まとめ
Gitlab.com上でGitlabが提供するSASTのテンプレートを使用してSemgrepを実行してみました。