Young Leaves

Bicep + KICS (Docker) でAzure リソースの脆弱性を検出する

今回はIaC から構成の脆弱性を検出するツール・KICS を使い、Bicep で記述したAzure リソースの脆弱性を検出する方法について説明します。

実施環境 (WSL)

OS

Ubuntu 24.04 LTS

Docker CE

27.2.0

KICS

v2.1.2

前提条件

今回はWSL 上でDocker を使います。WSL にDocker をインストールしていない場合は以下ドキュメントを参考にインストールしてください。

Install Docker Engine on Ubuntu

KICS とは

KICS - Keeping Infrastructure as Code Secure

KICS はCheckmarx 社が提供している静的コード解析ツールです。IaC やコンテナ関連の定義ファイル、API の定義などに関するセキュリティの脆弱性、コンプライアンスの問題、構成の誤りをチェックできます。また、Terraform のみですがチェック後に自動修正を行うこともできます。各種リソースの作成前にセキュリティリスクを洗い出し修正することにより、セキュアなリソースやAPI を作成できます。

KICS はGo 言語で開発されたツールで、IaC のチェックはOPA (Open Policy Agent) のRego を利用しています。詳細なアーキテクチャは以下ページを参照してください。

Architecture - KICS

KICS を使うには以下3つの方法があります。

  • Checkmarx 提供のコンテナイメージを実行する
  • Homebrew からインストールする (Mac OS)
  • GitHub のコードを手動ビルドし実行する

ローカルPC にあまりツールを入れたくない場合はDocker イメージを使います。Mac OS の場合はHomebrew でインストールできるためHomebrew で一元管理できます。

KICS でチェックできるツール

KICS では以下ツールの定義ファイルをチェックできます。

  • Ansible (Config、Inventoryも含む)
  • Azure Resource Manager (ARM)
  • Bicep
  • AWS CDK
  • CICD (GitHub Workflow file)
  • CloudFormation
  • Crossplane
  • Azure Blueprints
  • Docker (Docker Composer も含む)
  • gRPC
  • Helm
  • Knative
  • Kubernetes
  • OpenAPI
  • Pulumi
  • ServerlessFW
  • Google Deployment Manager
  • AWS SAM
  • Terraform

KICS でのBicep について

KICS ではBicep で作成されるAzure リソースのチェックができます。内部的には拡張子が .bicep の場合にARM フォルダ内のBicep 定義を参照しチェックします。チェックを行うファイルは拡張子が .bicep のファイルのみであり拡張子 .bicepparam のパラメーターファイルはチェックされません。チェックする定義 (クエリー) は以下から確認できます。

Azure Resource Manager - KICS

今回の構成

今回は以下のフォルダ構成とします。main.bicep ではApp Service プラン、App Service、SQL Database を作成します。

.
└── bicep
    └── main.bicep

脆弱性チェック用のBicep テンプレートファイルの準備

初めに脆弱性のチェックに使うBicep テンプレートファイルを準備します。セキュリティの脆弱性をあえて出すためSQL Database のパスワードをそのまま張り付けたりしていますが実務では行わないようにしてください。

param location string = resourceGroup().location
param sku string = 'F1'
param linuxFxVersion string = 'node|20-lts'
param administratorLogin string = 'sqluser'
param administratorLoginPassword string = '!WFER93jqFede'

// App Service Planを作成
resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: 'asp-kicsbiceptest'
  location: location
  properties: {
    reserved: true
  }
  sku: {
    name: sku
  }
  kind: 'linux'
}

// App Serviceを作成
resource appService 'Microsoft.Web/sites@2023-12-01' = {
  name: 'app-kicsbiceptest'
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: linuxFxVersion
    }
  }
}

// SQL Serverを作成
resource sqlServer 'Microsoft.Sql/servers@2023-08-01-preview' = {
  name: 'sql-kicsbiceptest'
  location: location
  properties: {
    administratorLogin: administratorLogin
    administratorLoginPassword: administratorLoginPassword
  }
}

// SQL Databaseを作成
resource sqlDB 'Microsoft.Sql/servers/databases@2023-08-01-preview' = {
  parent: sqlServer
  name: 'sqldb-kicsbiceptest'
  location: location
  sku: {
    name: 'Standard'
    tier: 'Standard'
  }
}

KICS イメージの取得

KICS にはCheckmarx より提供されている公式イメージがあるため、docker pull コマンドを使いイメージを取得します。

# KICSイメージを取得する
docker pull checkmarx/kics:latest

KICS でBicep テンプレートファイルをチェック

KICS イメージを取得後、Bicep テンプレートファイルをチェックします。docker run を使う場合は以下の構文となります。

docker run -t -v <スキャンするフォルダ名>:<コンテナ内で使うフォルダ名> checkmarx/kics scan -p <コンテナ内で使うフォルダ名> -o "<結果のファイルを出力するパス>"

例えば、bicep フォルダ内の .bicep ファイルをスキャンし結果を同じフォルダ内に出力したい場合は以下のコマンドとなります。コンテナ内のフォルダは path としていますが、個人の環境に合わせたフォルダ名も指定できます。

# KICSでBicepテンプレートファイルをチェックする
docker run -t -v ./bicep:/path checkmarx/kics scan -p /path -o "/path/"

特定のファイルのみチェックしたい場合はファイルを指定してスキャンします。

docker run -t -v ./bicep:/path checkmarx/kics scan -p /path/main.bicep -o "/path/"

フォルダ内に存在するファイルをスキャンすると、以下のような実行結果が表示されます。

testuser@windowspc:~/test$ docker run -t -v ./bicep:/path checkmarx/kics scan -p /path/ -o "/path/"

<省略>

Scanning with Keeping Infrastructure as Code Secure v2.1.2


Preparing Scan Assets: Done
Executing queries: [---------------------------------------------------] 100.00%



Website with 'Http20Enabled' Disabled, Severity: LOW, Results: 1
Description: 'Microsoft.Web/sites' should have 'Http20Enabled' enabled
Platform: AzureResourceManager
Learn more about this vulnerability: https://docs.kics.io/latest/queries/azureresourcemanager-queries/azure/70111098-7f85-48f0-b1b4-e4261cf5f61b

        [1]: ../../path/main.bicep:24

                023:   location: location
                024:   properties: {
                025:     serverFarmId: appServicePlan.id


Website Azure Active Directory Disabled, Severity: LOW, Results: 1
Description: WebApp should have Azure Active Directory  enabled with 'identity.type' set to 'SystemAssigned' or 'userAssignedIdentities' set to 'true'
Platform: AzureResourceManager
Learn more about this vulnerability: https://docs.kics.io/latest/queries/azureresourcemanager-queries/azure/e9c133e5-c2dd-4b7b-8fff-40f2de367b56

        [1]: ../../path/main.bicep:22

                021: resource appService 'Microsoft.Web/sites@2023-12-01' = {
                022:   name: 'app-kicsbiceptest'
                023:   location: location

<省略>

Results Summary:
CRITICAL: 0
HIGH: 1
MEDIUM: 4
LOW: 2
INFO: 0
TOTAL: 7

Generating Reports: Done

脆弱性の結果は以下のように出力されます。ファイル形式、ファイル名を指定しない場合はJSON 形式の result.json が作成されます。

{
	"kics_version": "v2.1.2",
	"files_scanned": 1,
	"lines_scanned": 51,
	"files_parsed": 1,
	"lines_parsed": 51,
	"lines_ignored": 0,
	"files_failed_to_scan": 0,
	"queries_total": 43,
	"queries_failed_to_execute": 0,
	"queries_failed_to_compute_similarity_id": 0,
	"scan_id": "console",
	"severity_counters": {
		"CRITICAL": 0,
		"HIGH": 1,
		"INFO": 0,
		"LOW": 2,
		"MEDIUM": 4,
		"TRACE": 0
	},
	"total_counter": 7,
	"total_bom_resources": 0,
	"start": "2024-09-07T06:17:06.321639652Z",
	"end": "2024-09-07T06:17:07.625976814Z",
	"paths": [
		"/path/"
	],
	"queries": [
		{
			"query_name": "Passwords And Secrets - Generic Password",
			"query_id": "487f4be7-3fd9-4506-a07a-eae252180c08",
			"query_url": "https://docs.kics.io/latest/secrets/",
			"severity": "HIGH",
			"platform": "Common",
			"cwe": "798",
			"cloud_provider": "COMMON",
			"category": "Secret Management",
			"experimental": false,
			"description": "Query to find passwords and secrets in infrastructure code.",
			"description_id": "d69d8a89",
			"files": [
				{
					"file_name": "../../path/main.bicep",
					"similarity_id": "0677aef268272d7dd73e6cfc8c341fd72b56fb7def8da5ebc2e523f8d563d058",
					"line": 38,
					"issue_type": "RedundantAttribute",
					"search_key": "",
					"search_line": 0,
					"search_value": "",
					"expected_value": "Hardcoded secret key should not appear in source",
					"actual_value": "Hardcoded secret key appears in source"
				}
			]
		},
<省略>

出力フォーマットをPDF 形式に指定するとPDF ファイルで出力できます。

# スキャン結果をPDF形式で出力する
docker run -t -v ./bicep:/path checkmarx/kics scan --report-formats "pdf" -p /path/ -o "/path/"

特定の重大度を除外したい場合は --exclude-severities オプションを使うことで除外できます。以下のコマンドはINFO とLOW を除外してスキャンします。info とlow のカンマの間にスペースを入れるとエラーとなるため注意してください。

# INFOとLOWの重大度を除外してスキャンする
docker run -t -v ./bicep:/path checkmarx/kics scan --exclude-severities 'info,low' -p /path/ -o "/path/"

その他詳細なオプションの使い方は以下ドキュメントを参照してください。

KICS CLI

KICS の設定ファイル化

KICS はCLI のオプション内容をJSON、YAML、TOML、HCL で設定ファイル化できます。設定ファイル化することにより、スキャン時のコマンドを簡素化できます。例はJSON で設定ファイル化したものとなります。

{
  "path": "bicep_sample",
  "verbose": true,
  "log-file": true,
  "type": "bicep",
  "queries-path": "assets/queries",
  "exclude-paths": [
     "hogehoge/"
  ],
  "output-path": "path"
}

設定ファイルを指定して実行するには --config オプションで指定します。

# 設定ファイルを指定してスキャンする
docker run -t -v ./bicep:/path checkmarx/kics scan -p /path/ --config ./bicep/kics-config.json

その他形式の記載方法は以下ドキュメントを参照してください。

Configuration - KICS

Bicep チェック時の一部項目除外

現時点でBicep チェック時に特定のブロックやラインを除外する kics-scan ignore-block などは利用できません。こちらを利用できるのはDockerfile、HCL (Terraform)、YAML 形式のファイルのみとなるため、--exclude-severities オプションでレベルを除外するなどで対応します。

CI にKICS を組み込む

IaC などをバージョン管理ツールにPush した時にKICS を実行させることもできます。今回はGitHub にBicep のテンプレートファイルをPush 時にKICS を実行します。Checkmarx にてGitHub Actions 用のワークフローが提供されているため、こちらを使い作成します。

Checkmarx/kics-github-action: GitHub actions of KICS scan - Keeping Infrastructure as Code Secure

例えばGitHub へPush 時にKICS でチェックしjson ファイルを表示するには以下のようなワークフローファイルを作成します。特定のブランチで実行したい、など条件を追加する場合はブランチ名の指定も行ってください。

name: Run KICS
run-name: Run KICS

on: [push]

jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
        # GitHubリポジトリにアクセス可能にする
        - uses: actions/checkout@v3
        # KICSでIaCをスキャンする
        - name: run kics Scan
          uses: checkmarx/kics-github-action@v2.1.0
          with:
            # bicepフォルダをスキャンする
            path: 'bicep'
            output_path: result/
        # 結果をJSONフォーマットで表示する
        - name: display kics results
          run: |
            cat result/results.json

実行後、GitHub Actions のジョブ画面で検知された内容を確認できます。

デフォルトではエラーがある場合にジョブを失敗とするため、参考例のBicep テンプレートファイルで実行するとエラーとなります。スキャン結果を無視する場合は ignore_on_exit で results を設定します。

name: Run KICS
run-name: Run KICS

on: [push]

jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
        # GitHubリポジトリにアクセス可能にする
        - uses: actions/checkout@v3
        # KICSでIaCをスキャンする
        - name: run kics Scan
          uses: checkmarx/kics-github-action@v2.1.0
          with:
            # bicepフォルダをスキャンする
            path: 'bicep'
            output_path: result/
        # 結果をJSONフォーマットで表示する
        - name: display kics results
          run: |
            cat result/results.json

特定の重要度が検知された場合にジョブを失敗させるには fail_on で重要度を指定します。例はHIGH とMEDIUM が検知された時にジョブを失敗させます。

name: Run KICS
run-name: Run KICS

on: [push]

jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
        # GitHubリポジトリにアクセス可能にする
        - uses: actions/checkout@v3
        # KICSでIaCをスキャンする
        - name: run kics Scan
          uses: checkmarx/kics-github-action@v2.1.0
          with:
            # bicepフォルダをスキャンする
            path: 'bicep'
            fail_on: high,medium
            output_path: result/
        # 結果をJSONフォーマットで表示する
        - name: display kics results
          run: |
            cat result/results.json

まとめ

  • KICS はIaC や各種定義ファイルにおけるセキュリティの脆弱性、コンプライアンスの問題、誤った構成を検知できる静的コード解析ツール
  • Bicep では .bicep のテンプレートファイルのみチェックできる
  • 設定ファイルを作成することでCLI のコマンドを少なくできる
  • Bicep のチェックでは特定のブロックのみ除外はできないため、重要度を指定して対応する

参考資料