このドキュメントでは、Google Kubernetes Engine(GKE)クラスタとコンテナの潜在的なセキュリティ インシデントに対する一般的な軽減策と対応策について説明します。
このドキュメントは、GKE セキュリティ インシデントへの対応に関するガイダンスを探しているセキュリティ スペシャリストを対象としています。 Google Cloud のコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。
クラスタのセキュリティの強化の提案に従うと、GKE ワークロードのセキュリティが向上します。ただし、ワークロード保護の対策が行われていても、セキュリティ インシデントは発生します。
インシデントを検出する
潜在的なインシデントを検出するには、ワークロードのログの収集とモニタリングを行うプロセスを設定することをおすすめします。次に、ログから検出された異常イベントに基づくアラートを設定します。何か異常が検出された場合はセキュリティ チームに警告します。セキュリティ チームは潜在的なインシデントを確認できます。
アラートは、特定の指標やアクションに基づいてカスタマイズできます。たとえば、GKE ノードの CPU 使用率が高いとの警告があった場合は、クリプトマイニングに感染している可能性があります。
アラートは、ログと指標を集計して生成する必要があります。たとえば、GKE の監査ロギングと Cloud Logging のログに基づくアラートとを組み合わせて使用できます。
セキュリティ関連のクエリの詳細については、監査ロギングのドキュメントをご覧ください。
セキュリティ インシデントに対応する
インシデントのアラートがあったら対処してください。可能であれば、脆弱性を修正してください。脆弱性の根本原因がわからない、または修正の準備ができていない場合は、緩和策を適用します。
適用可能な緩和策は、インシデントの深刻度と問題を特定できたかどうかによって異なります。
このガイドでは、GKE で稼働中のワークロードでインシデントを検出後に行えるアクションについて説明します。重大度の高い順に、次のことを行えます。
- ホスト VM のディスクのスナップショットを作成する。スナップショットを使用すると、ワークロードの再デプロイまたは削除後に、異常時の VM の状態に関するフォレンジックを実施できます。
ワークロードの稼働中に VM を検査する。ホスト VM またはワークロード コンテナに接続すると、攻撃者のアクションに関する情報が得られます。ライブ VM の検査前にはアクセスを減らすことをおすすめします。
コンテナを再デプロイする。再デプロイすると、該当するコンテナで現在実行中のプロセスが停止されて再起動されます。
ワークロードを削除する。ワークロードを削除すると、該当するコンテナで現在実行中のプロセスが停止され、再起動されません。
このような緩和策については、次のセクションで説明します。
始める前に
このトピックで使用するメソッドでは、次の情報が使用されます。
- 不正使用されていると思われる Pod の名前、または
POD_NAME。 - コンテナまたは Pod を実行しているホスト VM の名前、または
NODE_NAME。
アクションを実施する前に、発見した場合に攻撃者から否定的な反応があるかどうかも検討してください。攻撃者は、データの削除やワークロードの破壊を行うことがあります。リスクが高すぎる場合は、調査を行う前に、ワークロードの削除など根本的な軽減策を検討してください。
VM のディスクのスナップショットを作成する
VM のディスクのスナップショットを作成すると、ワークロードの再デプロイまたは削除後にフォレンジック調査を行えます。スナップショットは、実行中のインスタンスにディスクが接続されたまま作成できます。
永続ディスクのスナップショットを作成するには、最初に VM にアタッチされているディスクを確認します。次のコマンドを実行して、
sourceフィールドを確認します。gcloud compute instances describe NODE_NAME --zone COMPUTE_ZONE \ --format="flattened([disks])"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となります。スナップショット作成を完了するには、次のコマンドを実行します。
gcloud compute disks snapshot DISK_NAME
詳細については、Compute Engine ドキュメントの永続ディスクのスナップショットを作成するをご覧ください。
VM を調べる
対応を講じる前に、攻撃者がどのようなアクセスを行っているかを検討します。コンテナの不正使用が疑われるが、攻撃者に知られたくない場合は、ワークロードを中断することなくコンテナに接続して検査できます。検査は、大がかりなアクションを行う前の迅速な調査に役立ちます。検査はワークロードへの影響の少ないアプローチでもありますが、それだけでインシデントが解決するわけではありません。
また、権限のある認証情報を使用してマシンにログインすることを避けるため、ライブ フォレンジック(GRR Rapid Response など)、ノード上のエージェント、ネットワーク フィルタリングをセットアップすることでワークロードを分析できます。
ライブ VM の検査前にアクセスを減らす
不正使用されているコンテナをホストする VM へのネットワーク アクセスを閉鎖、ドレイン、制限すると、不正使用されているコンテナをクラスタの他の部分からある程度分離できます。VM へのアクセスを制限すると、リスクは軽減されますが、攻撃者が重大な脆弱性を利用している場合は、攻撃者による環境内の移動を防止することはできません。
ノードを閉鎖し、そのノードから他のワークロードをドレインする
ノードを閉鎖してドレインすると、不正使用されているコンテナに存在するワークロードがクラスタ内の他の VM に移動します。閉鎖とドレインを行うと、攻撃者が同じノード上の他のワークロードに影響を与えにくくなります。攻撃者がワークロードの永続的な状態を検査(たとえば、コンテナ イメージの内容を検査)することを防止できるわけではありません。
kubectlを使用してノードを閉鎖し、他の Pod がそのノードでスケジュール設定されないようにします。kubectl cordon NODE_NAMEノードの閉鎖後、他の Pod のノードをドレインします。
隔離する Pod にラベルを付けます。
kubectl label pods POD_NAME quarantine=truePOD_NAMEは、隔離する Pod の名前に置き換えます。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 をホストするノードで次の手順を行います。
インスタンスにタグを付けて、新しいファイアウォール ルールを適用できるようにします。
gcloud compute instances add-tags NODE_NAME \ --zone COMPUTE_ZONE \ --tags quarantinequarantineタグの付いたインスタンスからのすべての下り(外向き)の 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 quarantinequarantineタグの付いたインスタンスへのすべての内向き TCP トラフィックを拒否するファイアウォール ルールを作成します。この内向きルールのpriorityを1に設定し、指定した 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 の外部アドレスを削除するには、次の手順を行います。
外部 IP を VM に関連付けるアクセス構成ファイルを探して削除します。最初に、VM を記述してアクセス設定を探します。
gcloud compute instances describe NODE_NAME \ --zone COMPUTE_ZONE --format="flattened([networkInterfaces])"nameとnatIPを含む行を見つけます。次のような行です。networkInterfaces[0].accessConfigs[0].name: ACCESS_CONFIG_NAME networkInterfaces[0].accessConfigs[0].natIP: EXTERNAL_IP_ADDRESS削除する外部 IP と一致する
natIPの値を探します。アクセス構成ファイルの名前をメモします。外部 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 への接続
- 中間 VM の公開鍵をホスト VM に追加します。詳細については、Compute Engine ドキュメントの SSH 認証鍵の追加と削除をご覧ください。
タグを中間 VM に追加します。
gcloud compute instances add-tags INTERMEDIATE_NODE_NAME \ --zone COMPUTE_ZONE \ --tags intermediate上り(内向き)を許可するルールを追加し、前に追加した拒否ルールをオーバーライドします。ルールを追加するには、次のコマンドを実行します。
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)への受信トラフィックが許可されます。priorityが0である拒否ルールがオーバーライドされます。内部 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 など)によって管理されている場合、ポッドを削除すると新しいポッドがスケジュール設定されます。このポッドが新しいコンテナを実行します。
再デプロイは次の場合に適しています。
- 脆弱性の原因が既知である。
- 攻撃者がコンテナを再び不正使用するには多大な労力または時間を要すると思われる。
- コンテナはすぐに再び侵害される可能性があると思われ、オフラインにしたくないため、サンドボックスに配置して影響を抑えるようにする予定である。
ワークロードを再デプロイする際に、他の侵害の可能性が高い場合は、GKE Sandbox などのサンドボックス環境にワークロードを配置することを検討してください。サンドボックス化すると、攻撃者がコンテナを再び侵害する場合に、ホストノードのカーネルへのアクセスが制限されます。
Kubernetes にコンテナを再デプロイするには、そのコンテナを含む Pod を削除します。
kubectl delete pods POD_NAME --grace-period=10
削除された Pod 内のコンテナが稼働し続ける場合は、ワークロードを削除できます。
サンドボックス内でコンテナを再デプロイするには、GKE Sandbox によるワークロード分離の強化の手順に沿って操作します。
ワークロードを削除する
Deployment や DaemonSet などのワークロードを削除すると、すべてのメンバーポッドが削除されます。そうしたポッド内のすべてのコンテナが停止します。ワークロードの削除は、次のような場合に効果的です。
- 進行中の攻撃を停止したい。
- ワークロードをオフラインにしたい。
- 攻撃を即座に停止することが、アプリケーションの稼働時間やフォレンジック分析よりも重要である。
ワークロードを削除するには、kubectl delete CONTROLLER_TYPE を使用します。たとえば、Deployment
を削除するには次のコマンドを実行します。
kubectl delete deployments DEPLOYMENT
ワークロードを削除しても関連する Pod やコンテナがすべて削除されない場合は、コンテナ ランタイムの CLI ツール crictl
を使用して手動で削除できます。
crictl を使用してコンテナを停止または削除します。
containerd のコンテナを停止するには、次のコマンドを実行します。
crictl stop CONTAINER
containerd のコンテナを削除するには、次のコマンドを実行します。
crictl rm -f CONTAINER
ホスト VM を削除する
。コンテナを削除または除去できない場合は、該当するコンテナをホストする仮想マシンを削除します。
Pod がまだ存在する場合は、次のコマンドでホスト 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