セキュリティ インシデントの緩和


このドキュメントでは、Google Kubernetes Engine(GKE)クラスタとコンテナの潜在的なセキュリティ インシデントに対する一般的な軽減策と対応策について説明します。

クラスタのセキュリティの強化の提案に従うと、GKE ワークロードのセキュリティを向上できます。ただし、ワークロード保護の対策が行われていても、セキュリティ インシデントは発生します。

インシデントの検出

潜在的なインシデントを検出するには、ワークロードのログの収集とモニタリングを行うプロセスを設定することをおすすめします。次に、ログから検出された異常イベントに基づくアラートを設定します。何か異常が検出された場合はセキュリティ チームに警告します。セキュリティ チームは潜在的なインシデントを確認できます。

ログからのアラートの生成

アラートは、特定の指標やアクションに基づいてカスタマイズできます。たとえば、GKE ノードの CPU 使用率が高いとの警告があった場合は、クリプトマイニングに感染している可能性があります。

アラートは、ログと指標を集計して生成する必要があります。たとえば、GKE の監査ロギングと Cloud Logging のログに基づくアラートとを組み合わせて使用できます。

GKE のログに基づくアラート設定の詳細については、GKE アプリのセキュリティ管理とフォレンジック分析をご覧ください。たとえば、セキュリティ関連のクエリについては、監査ログのドキュメントをご覧ください。

セキュリティ インシデントへの対応

インシデントのアラートがあったら対処してください。可能であれば、脆弱性を修正してください。脆弱性の根本原因がわからない、または修正の準備ができていない場合は、緩和策を適用します。

適用可能な緩和策は、インシデントの深刻度と問題を特定できたかどうかによって異なります。

このガイドでは、GKE で稼働中のワークロードでインシデントを検出後に行えるアクションについて説明します。重大度の高い順に、次のことを行えます。

このような緩和策については、次のセクションで説明します。

始める前に

このトピックで使用するメソッドでは、次の情報が使用されます。

  • 不正使用されていると思われる Pod の名前、または POD_NAME
  • コンテナまたは Pod を実行しているホスト VM の名前、または NODE_NAME

アクションを実施する前に、発見した場合に攻撃者から否定的な反応があるかどうかも検討してください。攻撃者は、データの削除やワークロードの破壊を行うことがあります。リスクが高すぎる場合は、調査を行う前に、ワークロードの削除など根本的な軽減策を検討してください。

VM のディスクのスナップショットを作成する

VM のディスクのスナップショットを作成すると、ワークロードの再デプロイまたは削除後にフォレンジック調査を行えます。スナップショットは、実行中のインスタンスにディスクが接続されたまま作成できます。

  1. 永続ディスクのスナップショットを作成するには、最初に VM にアタッチされているディスクを確認します。次のコマンドを実行して、source フィールドを確認します。

    gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \
        --format="flattened([disks])"
    
  2. disks[NUMBER].source が含まれる行を探します。出力は次のようになります。

    disks[0].source: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/zones/COMPUTE_ZONE/disks/DISK_NAME
    

    ディスク名は、最後のスラッシュの後のソース名の部分です。たとえば、ディスク名は gke-cluster-pool-1-abcdeffff-zgt8 となります。

  3. スナップショット作成を完了するには、次のコマンドを実行します。

    gcloud compute disks snapshot DISK_NAME
    

詳細については、Compute Engine ドキュメントの永続ディスクのスナップショットを作成するをご覧ください。

ワークロードの稼働中に VM を検査する

アクションを行う前に、攻撃者がどのようなアクセスを行っているかも検討します。コンテナの不正使用が疑われるが、攻撃者に知られたくない場合は、コンテナに接続して検査します。検査は、大がかりなアクションを行う前の迅速な調査に役立ちます。また、検査はワークロードへの影響の少ないアプローチですが、インシデントが停止するわけではありません。

また、権限のある認証情報を使用してマシンにログインしないためには、ライブ フォレンジック(GRR Rapid Response など)や、ノード上のエージェント、ネットワーク フィルタリングを設定するとワークロードを分析できます。おすすめのフォレンジック ツールの詳細については、GKE アプリのセキュリティ管理とフォレンジック分析をご覧ください。

ライブ VM の検査前にアクセスを減らす

不正使用されているコンテナをホストする VM へのネットワーク アクセスを閉鎖ドレイン、制限すると、不正使用されているコンテナをクラスタの他の部分からある程度分離できます。VM へのアクセスを制限すると、リスクは軽減されますが、攻撃者が重大な脆弱性を利用している場合は、攻撃者による環境内の移動を防止することはできません。

ノードを閉鎖し、そのノードから他のワークロードをドレインする

ノードを閉鎖してドレインすると、不正使用されているコンテナに存在するワークロードがクラスタ内の他の VM に移動します。閉鎖とドレインを行うと、攻撃者が同じノード上の他のワークロードに影響を与えにくくなります。攻撃者がワークロードの永続的な状態を検査(たとえば、コンテナ イメージの内容を検査)することを防止できるわけではありません。

  1. kubectl を使用してノードを閉鎖し、他の Pod がそのノードでスケジュール設定されないようにします。

    kubectl cordon NODE_NAME
    

    ノードの閉鎖後、他の Pod のノードをドレインします。

  2. 隔離する Pod にラベルを付けます。

    kubectl label pods POD_NAME quarantine=true
    

    POD_NAME は、隔離する Pod の名前に置き換えます。

  3. quarantine のラベルが付いていない Pod のノードをドレインします。

    kubectl drain NODE_NAME --pod-selector='!quarantine'
    

ノードへのネットワーク アクセスを制限する

内部トラフィックと外部トラフィックの両方の、ホスト VM へのアクセスをブロックすることをおすすめしました。次に、ネットワークまたは VPC 上の特定の VM からの受信接続を検疫 VM に接続できるようにします。

最初の手順として、VM を所有するマネージド インスタンス グループからその VM を放棄します。VM を放棄すると、調査の完了前にノードに異常のマークが付くことや、自動修復(再作成)されることがなくなります。

VM を放棄するには、次のコマンドを実行します。

gcloud compute instance-groups managed abandon-instances INSTANCE_GROUP_NAME \
    --instances=NODE_NAME

VM をファイアウォールで保護する

同じネットワーク内の影響を受けるコンテナと他のワークロード間にファイアウォールを作成すると、さらなる分析の実施中に、攻撃者が環境内の他の部分に移動することを防止できます。すでに他のコンテナの VM をドレインしてあるため、影響を受けるのは検疫されるコンテナのみです。

以下の手順で VM をファイアウォールで保護すると、次のことを防止できます。

  • 外向きルールを使用して、クラスタ内の他の VM に新しい送信接続を行う。
  • 上り(内向き)ルールを使用して、不正使用されている VM に受信接続を行う。

VM を他のインスタンスからファイアウォールで保護するには、隔離する Pod をホストするノードで次の手順を行います。

  1. インスタンスにタグを付けて、新しいファイアウォール ルールを適用できるようにします。

    gcloud compute instances add-tags NODE_NAME \
        --zone COMPUTE_ZONE \
        --tags quarantine
    
  2. quarantine タグの付いたインスタンスからのすべての下り(外向き)の TCP トラフィックを拒否するファイアウォール ルールを作成します。

    gcloud compute firewall-rules create quarantine-egress-deny \
        --network NETWORK_NAME \
        --action deny \
        --direction egress \
        --rules tcp \
        --destination-ranges 0.0.0.0/0 \
        --priority 0 \
        --target-tags quarantine
    
  3. quarantine タグの付いたインスタンスへのすべての内向き TCP トラフィックを拒否するファイアウォール ルールを作成します。この内向きルールの priority1 に設定し、指定した VM からの SSH を許可する別のルールが優先されるようにします。

    gcloud compute firewall-rules create quarantine-ingress-deny \
        --network NETWORK_NAME \
        --action deny \
        --direction ingress \
        --rules tcp \
        --source-ranges 0.0.0.0/0 \
        --priority 1 \
        --target-tags quarantine
    

VM の外部 IP アドレスを削除する

VM の外部 IP アドレスを削除すると、VPC 外部の既存のネットワーク接続が切断されます。

VM の外部アドレスを削除するには、次の手順を行います。

  1. 外部 IP を VM に関連付けるアクセス構成ファイルを探して削除します。最初に、VM を記述してアクセス設定を探します。

    gcloud compute instances describe NODE_NAME \
        --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"
    

    namenatIP を含む行を見つけます。次のような行です。

    networkInterfaces[0].accessConfigs[0].name:              ACCESS_CONFIG_NAME
    networkInterfaces[0].accessConfigs[0].natIP:             EXTERNAL_IP_ADDRESS
    
  2. 削除する外部 IP と一致する natIP の値を探します。アクセス構成ファイルの名前をメモします。

  3. 外部 IP を削除するには、次のコマンドを実行します。

    gcloud compute instances delete-access-config NODE_NAME \
        --access-config-name "ACCESS_CONFIG_NAME"
    

中間 VM 経由でホスト VM に SSH 接続する

ホスト VM の外部 IP を削除すると、VPC 外部から SSH 接続できなくなり、同じネットワーク内の別の VM からアクセスすることになります。このセクションでは以後、これを中間 VM と呼びます。

前提条件

  • ホスト VM のサブネットワークにアクセスできる中間 VM。まだない場合は、それ用の VM を作成してください。
  • 中間 VM の内部 IP アドレス。
  • 中間 VM からの SSH 公開鍵。詳細については、SSH 認証鍵の管理をご覧ください。

ホスト VM への接続

  1. 中間 VM の公開鍵をホスト VM に追加します。詳細については、Compute Engine ドキュメントの SSH 認証鍵の追加と削除をご覧ください。
  2. タグを中間 VM に追加します。

    gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \
      --zone COMPUTE_ZONE \
      --tags intermediate
    
  3. 上り(内向き)を許可するルールを追加し、前に追加した拒否ルールをオーバーライドします。ルールを追加するには、次のコマンドを実行します。

    gcloud compute firewall-rules create quarantine-ingress-allow \
        --network NETWORK_NAME \
        --action allow \
        --direction ingress \
        --rules tcp:22 \
        --source-tags intermediate \
        --priority 0 \
        --target-tags quarantine
    

    このルールでは、ネットワーク内の intermediate タグ付きの VM からポート 22(SSH)への受信トラフィックが許可されます。priority0 である拒否ルールがオーバーライドされます。

  4. 内部 IP を使用して、隔離された VM に接続します。

    ssh -i KEY_PATH USER@QUARANTINED_VM_INTERNAL_IP
    

    次のように置き換えます。

    • KEY_PATH: SSH 秘密鍵のパス。
    • USER: Google Cloud アカウントのメールアドレス。
    • QUARANTINED_VM_INTERNAL_IP: 内部 IP アドレス。

コンテナを再デプロイする

コンテナを再デプロイすると、コンテナの新しいコピーが起動され、不正使用されたコンテナが削除されます。

コンテナを再デプロイするには、コンテナをホストするポッドを削除します。ポッドが上位の Kubernetes 構成要素(Deployment や DaemonSet など)によって管理されている場合、ポッドを削除すると新しいポッドがスケジュール設定されます。このポッドが新しいコンテナを実行します。

再デプロイは次の場合に適しています。

  • 脆弱性の原因が既知である。
  • 攻撃者がコンテナを再び不正使用するには多大な労力または時間を要すると思われる。

Kubernetes にコンテナを再デプロイするには、そのコンテナを含む Pod を削除します。

kubectl delete pods POD_NAME --grace-period=10

削除された Pod 内のコンテナが稼働し続ける場合は、ワークロードを削除できます。

ワークロードを削除する

Deployment や DaemonSet などのワークロードを削除すると、すべてのメンバーポッドが削除されます。そうしたポッド内のすべてのコンテナが停止します。ワークロードの削除は、次のような場合に効果的です。

  • 進行中の攻撃を停止したい。
  • ワークロードをオフラインにしたい。
  • 攻撃を即座に停止することが、アプリケーションの稼働時間やフォレンジック分析よりも重要である。

ワークロードを削除するには、kubectl delete CONTROLLER_TYPE を使用します。たとえば、Deployment を削除するには次のコマンドを実行します。

kubectl delete deployments DEPLOYMENT

ワークロードを削除しても関連する Pod やコンテナがすべて削除されない場合は、コンテナ ランタイムの CLI ツール(通常は docker)を使用して手動で削除できます。ノードで containerd が実行されている場合は、crictl を使用します。

Docker

Docker コンテナ ランタイムの使用中にコンテナを停止するには、docker stop または docker kill を使用します。

docker stop では、SIGTERM シグナルをルートプロセスに送信し、デフォルトでプロセスが終了するまで 10 秒待つことで、コンテナを停止します。その期間内にプロセスが終了しない場合は、SIGKILL シグナルを送信します。この猶予期間は --time オプションで指定できます。

docker stop --time TIME_IN_SECONDS CONTAINER

docker kill はコンテナを停止する最も速い方法です。すぐに SIGKILL シグナルが送信されます。

docker kill CONTAINER

docker rm -f という 1 つのコマンドでコンテナを停止して削除することもできます。

docker rm -f CONTAINER

containerd

GKE で containerd ランタイムを使用している場合は、crictl でコンテナを停止または削除します。

containerd のコンテナを停止するには、次のコマンドを実行します。

crictl stop CONTAINER

containerd のコンテナを削除するには、次のコマンドを実行します。

crictl rm -f CONTAINER

ホスト VM の削除

コンテナを削除または除去できない場合は、該当するコンテナをホストする仮想マシンを削除します。

ポッドがまだ存在する場合は、次のコマンドでホスト VM の名前を確認できます。

kubectl get pods --all-namespaces \
  -o=custom-columns=POD_NAME:.metadata.name,INSTANCE_NAME:.spec.nodeName \
  --field-selector=metadata.name=POD_NAME

ホスト VM を削除するには、次の gcloud コマンドを実行します。

gcloud compute instance-groups managed delete-instances INSTANCE_GROUP_NAME \
    --instances=NODE_NAME

マネージド インスタンス グループからインスタンスを破棄すると、グループのサイズが VM 1 台分だけ小さくなります。次のコマンドを使用すると、1 つのインスタンスをグループに手動で再び追加できます。

gcloud compute instance-groups managed resize INSTANCE_GROUP_NAME \
    --size=SIZE

次のステップ