06 / Learn — Kubernetes Security

Kubernetesオーケストレーション層のセキュリティ

コンテナイメージが安全でも、Kubernetesクラスタの設定が緩ければ攻撃者はそこを突破口にします。このページでは EKS・AKS・GKE を横断して、RBAC、Pod Security Standards、NetworkPolicy、Admission Controlという「オーケストレーション層」の制御を扱います。コンテナイメージやビルド時のセキュリティは Container Security のページで別途扱います。

Why It Matters

なぜオーケストレーション層の制御が重要なのか

Kubernetesはデフォルトで「性善説」に近い設計になっています。NetworkPolicyを何も定義しなければ全Podが全Podと通信でき、ServiceAccountトークンはデフォルトで各Podに自動マウントされ、Pod Security Admissionを明示的に強制しなければ特権コンテナの起動を止める仕組みは働きません。つまりクラスタは「何も設定しなければ最も緩い状態」で動き続けます。

1つのPodの侵害が、クラスタ全体の侵害につながる

脆弱なアプリケーションが動くPodが1つ侵害されただけでも、そのPodが特権コンテナで動いていたり、過剰な権限を持つServiceAccountを使っていれば、攻撃者はノードへのエスケープやクラスタ全体のリソース列挙まで到達できます。

Architecture

典型的なクラスタ制御アーキテクチャ

クラスタへのすべての変更はkube-apiserverを経由します。Admission Controlはこの経路上に位置する「最後の砦」であり、ここでPodの起動を許可するかどうかが決まります。

Admission Controlの段階が「Security Gate」です。ここでPod Security Admissionやポリシーエンジンが特権コンテナ・hostPath・hostNetworkの利用を拒否できなければ、etcdに書き込まれた設定はそのままノード上で実行されてしまいます。

Key Concepts

主要概念とEKS/AKS/GKEの対応

EKS、AKS、GKEの主要概念の対応表
概念 EKS (AWS) AKS (Azure) GKE (Google Cloud)
クラウドIAMとのRBAC連携 IRSA (IAM Roles for Service Accounts) Azure AD Workload Identity Workload Identity Federation
デフォルトのPod Security強制 強制なし(手動でPSAラベル付与が必要) 強制なし(Azure Policyアドオンで補完) Autopilotはrestricted相当を既定で強制
NetworkPolicyエンジン Amazon VPC CNI + Calico(要有効化) Azure Network Policy / Calico(要有効化) Calico(GKEに組み込み、有効化が必要)
コントロールプレーンの監査ログ EKS control plane logging (CloudWatch Logs) AKS Diagnostic settings GKE Audit Logs (Cloud Audit Logs)
RBAC Pod Security Standards NetworkPolicy Admission Control Kyverno OPA Gatekeeper
Common Misconfigurations

よくある設定ミス

  • 特権コンテナの起動 High Risk

    privileged: truehostNetwork: true / hostPID: true を持つコンテナは、ホストとほぼ同等の権限で動作し、Pod境界を無意味にする。

  • 過剰なClusterRoleBinding High Risk

    cluster-adminがdefault ServiceAccountや特定Namespace全体に紐づけられ、検証用の設定がそのまま本番に残るケース。

  • NetworkPolicy未設定 Medium Risk

    NetworkPolicyが1つも定義されておらず、クラスタ内の全Podが全Podへ自由に到達できる状態になっている。

  • Pod Security Admissionの未強制 High Risk

    Namespaceにpod-security.kubernetes.io/enforceラベルが設定されておらず、実質的にprivilegedレベルのまま運用されている。

  • シークレットの平文環境変数マウント Medium Risk

    APIキーやDB認証情報がSecretsマネージャーやCSIドライバ経由ではなく、Podの環境変数に平文で渡され、kubectl describeやログから漏洩しやすくなる。

Attack Scenario

攻撃シナリオ: 特権Podからのクラスタ侵害

攻撃者が脆弱なWebアプリケーションのコンテナ実行権限(RCE)を獲得した、という想定です。

  1. 侵害したPod内から、マウントされているdefault ServiceAccountの権限を確認する。
  2. そのPodがprivilegedで動作しているかをクラスタ全体で調査する。
  3. hostPath/hostNetworkの利用有無から、ノードへのエスケープ経路を探す。
  4. 特権コンテナのホストファイルシステムアクセスを悪用し、ノード上で任意コマンドを実行する。
bash
# 1. マウントされたdefault ServiceAccountの権限を確認
$ kubectl auth can-i --list --as=system:serviceaccount:default:default

# 2. クラスタ全体で特権コンテナを検索
$ kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged==true) | .metadata.name'

# 3. 発見した特権Podのspecを確認(hostPath/hostNetworkの有無)
$ kubectl get pod vulnerable-app-7d9f8 -n default -o yaml | grep -E 'privileged|hostNetwork|hostPath'

# 4. 特権コンテナ内からホストのファイルシステムへアクセス
$ kubectl exec -it vulnerable-app-7d9f8 -n default -- chroot /host /bin/bash
Detection

検知

Kubernetes監査ログとクラウドネイティブな脅威検知サービスを組み合わせ、以下のようなシグナルにアラートを設定します。

  • Podのcreate/updateイベントでsecurityContext.privileged: trueを含むもの。
  • Kyvernoのポリシーレポート(PolicyReport / ClusterPolicyReport)でfail判定が急増している。
  • kube-benchによるCIS Kubernetes Benchmark定期スキャンの失敗項目。
  • GuardDuty for EKS / Microsoft Defender for Containers / GKE Security Postureが検出する異常な特権昇格・不審なプロセス実行。
Kubernetes audit log query (example)
SELECT stageTimestamp, user.username, verb, objectRef.namespace, objectRef.name
FROM kubernetes_audit_logs
WHERE verb IN ('create', 'update')
  AND objectRef.resource = 'pods'
  AND requestObject.spec.containers[*].securityContext.privileged = true
ORDER BY stageTimestamp DESC;
Remediation

是正

該当Namespaceに対してPod Security Admissionを強制し、PodのsecurityContextを最小権限の設定へ書き換えます。

bash
# Namespaceに restricted レベルのPod Security Admissionを強制
$ kubectl label namespace default pod-security.kubernetes.io/enforce=restricted --overwrite

# default ServiceAccountの自動マウントを無効化
$ kubectl patch serviceaccount default -n default -p '{"automountServiceAccountToken": false}'

# 過剰なClusterRoleBindingを削除
$ kubectl delete clusterrolebinding default-cluster-admin-binding

PodのsecurityContextは以下のように変更します。

securityContext: before / after
# Before (危険な設定)
securityContext:
  privileged: true
  runAsUser: 0

# After (最小権限)
securityContext:
  privileged: false
  allowPrivilegeEscalation: false
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  capabilities:
    drop:
      - ALL
Hands-on Lab

実際に手を動かす

このページで扱った「特権コンテナによるクラスタ侵害」の再現と是正を、実際のシナリオ形式で体験できます。Scenario → Architecture → CLI Commands → Misconfiguration → Detection → Remediation → Verification の流れで進めます。

Lab: Kubernetes Privileged Container を始める →
Checklist

実装チェックリスト