本記事はサーバーワークス Advent Calendar 2023 の8日目の記事です。
こんにちは。アプリケーションサービス部の兼安です。
今回はセキュリティのお話です。
日々ソフトウェアの改善を行う中で、スピードとセキュリティの両立にお悩みの方も多いのではないでしょうか。
今回は、脆弱性を管理するSBOMという仕組みを、OSSのTrivyというツールを使ってご紹介します。
- 本記事のターゲット
- 本記事執筆に用いた環境
- SBOMとは
- SBOMを取り巻く状況
- Trivyで脆弱性を検知する
- Trivyの解析結果をSBOM形式で出力する
- GitHub ActionsでTrivyを使う
- GitHubのDependency graphとTrivy
- まとめ
本記事のターゲット
本記事は、以下のような方を対象としています。
- SBOMが何なのか知りたい方
- どうやったらSBOMを利用できるのか知りたい方
本記事執筆に用いた環境
- macOS 14.11
- Trivy 0.48.0
SBOMとは
SBOMとは、Software Bill of Materialsの略称です。
SBOMは、ソフトウェアコンポーネントやそれらの依存関係をリスト化したものです。
国際的な標準規格がいくつかあります。
以下は代表例です。
規格が整っているので、機械処理可能になっているのが特徴です。
SBOMを使用する目的は、以下のものがあります。
- ソフトウェアコンポーネントの脆弱性管理
- ソフトウェアコンポーネントのライセンス管理
- 管理コストの削減
- 脆弱性の少ない製品が増えることで、サイバー衛生を向上させる
4つ目は、SBOMに対応したソフトウェアが増えたら暁には、の話ですね。
本記事では、この中から脆弱性管理についてご紹介します。
参考
経済産業省 - ソフトウェア管理に向けたSBOM(Software Bill of Materials)の導入に関する手引 Ver. 1.0
SBOMを取り巻く状況
ソフトウェア開発におけるSBOMの対応状況は、業界ごとによって異なります。
下記の資料を見る限り、現状医療業界がもっとも進んでいます。
公共性の強い業界ほど、SBOMの議論が進んでいるようです。
基準・ガイドラインに関連付いた業界の解説文書、業界セミナーなどでSBOMガイダンスの参照・推奨を受けデファクト化を推進。 (規制当局・認証機関におけるSBOMガイダンスの活用促進)
引用元
「本事業の成果物を活用したSBOM普及促進策案」(P33)より
経済産業省 - サイバー・フィジカル・セキュリティ確保に向けたソフトウェア管理手法等検討タスクフォースの検討の方向性
医療業界では、 今年の春に薬事法の改正がありました。
ここでSBOMが必要になることの記載があります。
(4) JIS T 81001―5―1の箇条8のソフトウェア構成管理プロセスについて 構成管理プロセスは、当該医療機器のソフトウェア部品表(SBOM)を適切に作成することによって確認すること。
引用元
厚生労働省 - 医療機器の基本要件基準第12条第3項の適合性の確認について
この文書には、1年間の経過措置期間が設定されるとあります。
従って、2024年以降だと医療に関わるシステムには
私自身は医療業界に携わっていないので、主観しか述べることはできませんが、医療業界では2024年に向けてSBOMの対応が進んでいると考えられます。
今後、各業界においてSBOMの必要性が高まることが予想されます。
来るべき時に備えて、少しずつ準備を進めていくのがよいと思います。
Trivyで脆弱性を検知する
Trivyは、脆弱性を検知するOSSのツールです。
Trivyは、コンテナイメージやアプリケーションのソフトウェアコンポーネントを検知し、SBOMとして出力することができます。
早速やってみましょう。
Trivyの公式ドキュメントに従ってインストールします。
aquasecurity.github.io
Flaskのプロジェクトを作ります。 Pipfileは以下のようになります。
[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] flask = "*" [dev-packages] [requires] python_version = "3.11"
これに基づきライブラリをインストール後、Trivyでスキャンをかけます。
今回は簡単にするため、コンテナを使わずファイルシステムに対してスキャンをかけます。
trivy fs ./
fs
がファイルシステムのスキャンを意味します。
./
はカレントディレクトリを意味します。
$trivy fs ./ 2023-12-06T20:12:51.087+0900 INFO Loaded trivy.yaml 2023-12-06T20:12:51.104+0900 INFO Vulnerability scanning is enabled 2023-12-06T20:12:51.104+0900 INFO Secret scanning is enabled 2023-12-06T20:12:51.104+0900 INFO If your scanning is slow, please try '--scanners vuln' to disable secret scanning 2023-12-06T20:12:51.104+0900 INFO Please see also https://aquasecurity.github.io/trivy/v0.48/docs/scanner/secret/#recommendation for faster secret detection 2023-12-06T20:12:51.123+0900 INFO Number of language-specific files: 1 2023-12-06T20:12:51.123+0900 INFO Detecting pipenv vulnerabilities...
特に何も出ずに終わりました。
脆弱性は見つからなかったようです。
では、Flaskのバージョンを脆弱性が報告されているバージョンにして再試行してみます。
脆弱性はこちらを使用します。
Pipfileを以下のように修正します。
[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] flask = "2.3.1" [dev-packages] [requires] python_version = "3.11"
この状態でライブラリを再インストール後、Trivyで再スキャンをかけます。
$trivy fs ./ 2023-12-06T20:19:17.159+0900 INFO Loaded trivy.yaml 2023-12-06T20:19:17.170+0900 INFO Vulnerability scanning is enabled 2023-12-06T20:19:17.170+0900 INFO Secret scanning is enabled 2023-12-06T20:19:17.170+0900 INFO If your scanning is slow, please try '--scanners vuln' to disable secret scanning 2023-12-06T20:19:17.170+0900 INFO Please see also https://aquasecurity.github.io/trivy/v0.48/docs/scanner/secret/#recommendation for faster secret detection 2023-12-06T20:19:17.177+0900 INFO Number of language-specific files: 1 2023-12-06T20:19:17.177+0900 INFO Detecting pipenv vulnerabilities... Pipfile.lock (pipenv) Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) ┌─────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬────────────────────────────────────────────────────────────┐ │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │ ├─────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼────────────────────────────────────────────────────────────┤ │ flask │ CVE-2023-30861 │ HIGH │ fixed │ 2.3.1 │ 2.3.2, 2.2.5 │ flask: Possible disclosure of permanent session cookie due │ │ │ │ │ │ │ │ to missing Vary: Cookie... │ │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2023-30861 │ └─────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴────────────────────────────────────────────────────────────┘
脆弱性が検知されました。
出力されているURLから、想定していたものが検出されていることがわかります。
インストールされているライブラリに脆弱性が含まれていれば、Trivyはそれらを自動で検知可能で、脆弱性情報と結びつけることもできます。
終了コードの指定
Trivyのコマンドは、下記のようにすることで、脆弱性を検知した場合に終了コードを1にすることができます。
GitHub ActionsやAWS CodePipelineなどCI/CDは、プロセス内のコマンドが終了コードゼロ以外を返すと、プロセスを中断します。
従って、CI/CDに脆弱性検知を組み込み、検知したらデプロイしないようにすることも可能です。
trivy fs ./ --exit-code 1
Trivyの解析結果をSBOM形式で出力する
Trivyのコマンドは、--format
オプションで何も指定しなければ、表形式となります。
この場合、脆弱性が見つからなければ何も出力されません。
Trivyの検査結果をソフトウェアコンポーネントの一覧としてのSBOM形式のファイルで出力するには、--format
オプションでcyclonedx,spdx,spdx-json
などを指定します。
(ちなみに、--format
オプションで指定可能な値は、公式ドキュメントに載っていないので、--help
で確認するのをお勧めします。)
SBOMの代表的なフォーマットであるSPDXを指定してみると、以下のような出力になります。
--format
オプションを指定しない時と異なり、脆弱性が見つからなくても出力されているのがわかります。
これが、ソフトウェアコンポーネントの一覧としてのSBOMです。
これをいつでも提示可能にすることが、SBOM用いたソフトウェアコンポーネント管理の目的の一つです。
$ trivy fs ./ --format spdx-json --output spdx-json-by-trivy.json
SBOM形式での出力結果はこちら
上部が脆弱性なしのバージョンのFlaskを使用した結果、下部が脆弱性ありのバージョンのFlaskを使用した結果です。
gist.github.com
SBOM形式で出力すれば、それを元に脆弱性検知を行うこともできます。
つまり、自前で一気に脆弱性検知をすることもできれば、作成したSBOMを渡して、他者に脆弱性検知を行ってもらうこともできます。
$ trivy fs ./ --format spdx-json --output spdx-json-by-trivy.json $ trivy sbom spdx-json-by-trivy.json 2023-12-10T02:48:02.894Z INFO Vulnerability scanning is enabled 2023-12-10T02:48:02.895Z INFO Detected SBOM format: spdx-json 2023-12-10T02:48:02.898Z INFO Number of language-specific files: 1 2023-12-10T02:48:02.899Z INFO Detecting pipenv vulnerabilities... Pipfile.lock (pipenv) Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 1, CRITICAL: 0) ┌─────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬────────────────────────────────────────────────────────────┐ │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │ ├─────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼────────────────────────────────────────────────────────────┤ │ flask │ CVE-2023-30861 │ HIGH │ fixed │ 2.3.1 │ 2.3.2, 2.2.5 │ flask: Possible disclosure of permanent session cookie due │ │ │ │ │ │ │ │ to missing Vary: Cookie... │ │ │ │ │ │ │ │ https://avd.aquasec.com/nvd/cve-2023-30861 │ └─────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴────────────────────────────────────────────────────────────┘
GitHub ActionsでTrivyを使う
Trivyは、公式でGitHub Actionsがフォローされています。
プロジェクトフォルダに.github/workflows
フォルダを作成し、GitHub Actionsのワークフローを記述したYAMLファイルを作成します。
name: Trivy Vulnerability Scan on: push: branches: - main pull_request: jobs: build: name: Build runs-on: ubuntu-20.04 steps: - name: Checkout code uses: actions/checkout@v3 - name: Run Trivy vulnerability scanner in fs mode uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' trivy-config: trivy-config.yaml
ファイルシステムを対象に、trivy-config.yaml
を設定ファイルとして、脆弱性検知を実行します。
scan-ref: '.'
なので、trivy-config.yaml
はプロジェクト直下に置きます。
format: table exit-code: 1 severity: - UNKNOWN - LOW - MEDIUM - HIGH - CRITICAL
exit-code: 1
を指定して、脆弱性が見つかった場合はプロセスを中断するようにします。
この状態でFlaskを脆弱性があるバージョンにして、GitHub Actionsを実行します。
すると、GitHub Actionsが失敗し、脆弱性が見つかったことがわかります。
これで、脆弱性が見つかった場合、GitHub Actionsのワークフローで脆弱性検知し、プロセスを中断することができることがわかりました。
このように、GitHub ActionsにTrivyを組み込むことで、CI/CDに脆弱性検知を導入して脆弱性のあるコードをデプロイしないようにすることができます。
GitHubのDependency graphとTrivy
GitHub Actionsの流れでDependency graphに触れさせてください。
Dependency graphは、GitHubの機能の一つです。
有効にすると、GitHubのリポジトリにあるソフトウェアコンポーネントの依存関係を可視化することができます。
この機能を有効にすることで、ソフトウェアコンポーネントの管理と脆弱性検知を行うことができます。
Trivyによる解析と似た機能を持ちます。
現状、Dependency graphはデフォルトブランチがターゲットです。
デフォルトブランチがデフォルト設定のままなら、mainブランチがターゲットになります。
複数のブランチやプルリク時などをターゲットにする場合は、GitHub Actions+Trivyの方が便利そうです。
まとめ
今回は以上です。
SBOMの現状と、Trivyを使った脆弱性検知についてご紹介しました。
2023年12月現在、SBOMに対応したサービスも登場しつつありますが、基本的な動作を把握するためあえてTrivyを使ってみました。
使ってみたところ、よく悪くも便利すぎて一気に脆弱性検知ができてしまうので、肝心のSBOMが見ることができないという状況になりましたので、ゆっくりと触ってみたよかったと思います。
Trivyとtrivy-actionの動きが把握できたことで、CI/CDパイプラインに脆弱性管理を組み込み、安全なソフトウェアを提供する道筋が見えてきました。
SBOMに関してまた新しい情報が入りましたら、また記事にしたいと思います。
サーバーワークスでは、開発プロセスの最適化を支援するサービスを提供しています。
兼安 聡(執筆記事の一覧)
アプリケーションサービス部 DS3課所属
2024 Japan AWS Top Engineers (Database)
2024 Japan AWS All Certifications Engineers
認定スクラムマスター
広島在住です。今日も明日も修行中です。