Kubernetes環墁E��おける最も重要な10のセキュリチE��リスクとそ�E対策方況E/p>
OWASP Kubernetes Top 10は、Kubernetes環墁E��おける最も重大なセキュリチE��リスクを特定してぁE��す、EubernetesはコンチE��オーケストレーションの事実上�E標準となってぁE��すが、その柔軟性と褁E��性は数多くのセキュリチE��課題をもたらします。本ガイドでは、ワークロード�E設定ミス、RBACの問題、シークレチE��管琁E��ネチE��ワーク刁E��などを網羁E��ます、E/p>
安�EでなぁE��ークロード設定�E、KubernetesセキュリチE��における最も一般皁E��問題です。rootとして実行されるコンチE��、E��剰な権限、書き込み可能なファイルシスチE��、リソース制限なし�E設定�E重大な攻撁E��を生み出します。デフォルト設定�E多くの場合安�Eではなく、�E示皁E��強化する忁E��があります、E/p>
root権限とホストアクセスを持つ侵害されたコンチE��は、コンチE��サンド�EチE��スから脱出し、�EストファイルシスチE��にアクセスし、他�Eワークロードに侵入できます。設定ミスのあるPodからの権限�E格は、クラスタ全体�E侵害につながる可能性があります、E/p>
apiVersion: v1 kind: Pod metadata: name: insecure-app spec: containers: - name: app image: myapp:latest # Mutable tag! securityContext: privileged: true # Full host access! runAsUser: 0 # Running as root! volumeMounts: - mountPath: /host name: host-fs volumes: - name: host-fs hostPath: path: / # Entire host filesystem!
apiVersion: v1 kind: Pod metadata: name: secure-app spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: app image: myapp@sha256:abc123... # Immutable digest securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsUser: 1000 capabilities: drop: ["ALL"] resources: limits: cpu: "500m" memory: "256Mi" requests: cpu: "100m" memory: "128Mi"
KubernetesのRBAC(ロールベ�Eスアクセス制御)は強力ですが褁E��です。過度に寛容なロール、特にcluster-adminバインチE��ング、ワイルドカード権限、E��剰なサービスアカウント権限�E、クラスタリソース、シークレチE��、ワークロードへの不正アクセスを許可します、E/p>
過度な権限を持つサービスアカウントへのアクセスを得た攻撁E��E�E、シークレチE��の一覧表示、特権付きPodの作�E、デプロイメント�E変更、cluster-adminへの昁E��が可能です。ワイルドカードRBACルールは、Kubernetesにおけるroot権限�E付与に相当します、E/p>
# ClusterRoleBinding granting cluster-admin to a service account apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: app-admin-binding subjects: - kind: ServiceAccount name: my-app # App SA with cluster-admin! namespace: default roleRef: kind: ClusterRole name: cluster-admin # Full cluster control! apiGroup: rbac.authorization.k8s.io
# Scoped Role with minimum required permissions apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: app-role namespace: my-app-ns rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list"] # Read-only, specific resources resourceNames: ["app-config"] # Named resource only --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: app-role-binding namespace: my-app-ns subjects: - kind: ServiceAccount name: my-app namespace: my-app-ns roleRef: kind: Role name: app-role apiGroup: rbac.authorization.k8s.io
KubernetesのSecretsは、デフォルトではbase64エンコードされてぁE��だけで、暗号化されてぁE��せん。機寁E��ータ(APIキー、データベ�Eスパスワード、TLS証明書)を平斁E�EConfigMap、環墁E��数、暗号化されてぁE��いSecretsに保存すると、APIアクセス権を持つ誰にでも晒されます。また、etcdでの静止状態�E暗号化が有効になってぁE��ぁE��合、Secretsはetcdで可視化されます、E/p>
漏洩したシークレチE��により、攻撁E��E�EチE�Eタベ�Eス、クラウドアカウント、外部サービスへアクセスできます。暗号化なしでetcdに保存されたSecretsは、etcdアクセス権を持つ誰でも読み取れます。環墁E��数のシークレチE��は、Pod仕様やプロセスリストで可視化されます、E/p>
# Secret in plain ConfigMap Evisible to anyone apiVersion: v1 kind: ConfigMap metadata: name: app-config data: DB_PASSWORD: "SuperSecret123!" # Plaintext password! API_KEY: "sk-live-abc123xyz" # API key in ConfigMap! --- apiVersion: v1 kind: Pod metadata: name: app spec: containers: - name: app image: myapp:latest envFrom: - configMapRef: name: app-config # All values as env vars!
# Use External Secrets Operator with a vault backend apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: app-secrets spec: refreshInterval: 1h secretStoreRef: name: vault-backend kind: ClusterSecretStore target: name: app-secrets data: - secretKey: db-password remoteRef: key: secret/myapp/db property: password --- apiVersion: v1 kind: Pod metadata: name: app spec: containers: - name: app image: myapp@sha256:abc123... volumeMounts: - name: secrets mountPath: /etc/secrets readOnly: true # Mount as read-only files volumes: - name: secrets secret: secretName: app-secrets
クラスタレベルのポリシーがなければ、安�EでなぁE��ークロード�EチE�Eロイを防ぐガードレールはありません。Pod Security Standards(PSS)、アドミチE��ョンコントローラ、OPA GatekeeperやKyvernoなどのポリシーエンジンは、すべてのnamespaceでセキュリチE��ベ�Eスラインを実施するために不可欠です、E/p>
ポリシー実施がなければ、どの開発老E��も特権付きコンチE��をデプロイし、hostPathボリュームを使用し、セキュリチE��コントロールを無効化できます。単一の設定ミスのあるワークロードがクラスタ全体を侵害する可能性があります。手動レビューでは、すべての違反を検�Eするのに拡張できません、E/p>
#!/bin/bash # No admission control Eany pod spec is accepted # No Pod Security Standards configured # Anyone can deploy a privileged container kubectl run hacker-pod --image=alpine \ --overrides='{"spec":{"containers":[{ "name":"hack", "image":"alpine", "securityContext":{"privileged":true}, "command":["nsenter","--target","1","--mount","--uts","--ipc","--net","--pid","--","bash"] }]}}' # No policy blocks this Enow has host root access!
# Enforce Pod Security Standards with Kyverno apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: disallow-privileged spec: validationFailureAction: Enforce background: true rules: - name: deny-privileged match: any: - resources: kinds: ["Pod"] validate: message: "Privileged containers are not allowed." pattern: spec: containers: - securityContext: privileged: "false" - name: require-run-as-non-root match: any: - resources: kinds: ["Pod"] validate: message: "Containers must run as non-root." pattern: spec: securityContext: runAsNonRoot: true
チE��ォルトでは、Kubernetesクラスタ冁E�EすべてのPodは制限なしに相互通信できます。このフラチE��なネットワークアーキチE��チャは、侵害されたPodが他�EPod、サービス、さらにはKubernetes APIサーバ�Eに到達できることを意味します。�EイクロセグメンチE�Eションを実裁E��るには、NetworkPolicyが不可欠です、E/p>
ネットワーク刁E��がなければ、横方向�E移動�E簡単です。侵害されたフロントエンドPodは、バチE��エンドデータベ�Eス、�E部サービス、メタチE�EタAPI(169.254.169.254)に直接アクセスできます。これ�Eネットワーク層での最小権限�E原則に違反します、E/p>
# No NetworkPolicy Eall pods can communicate freely apiVersion: v1 kind: Namespace metadata: name: production # No default deny policy # No network policies at all # Any pod can reach: # - Other pods in any namespace # - Kubernetes API server # - Cloud metadata API (169.254.169.254) # - External internet
# Default deny all ingress and egress apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-all namespace: production spec: podSelector: {} policyTypes: ["Ingress", "Egress"] --- # Allow only frontend to backend communication apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-frontend-to-backend namespace: production spec: podSelector: matchLabels: app: backend policyTypes: ["Ingress"] ingress: - from: - podSelector: matchLabels: app: frontend ports: - port: 8080 protocol: TCP
Kubernetesコントロールプレーンコンポ�EネンチEAPIサーバ�E、etcd、kubelet、ダチE��ュボ�EチEとアプリケーションサービスは、誤ってインターネットや信頼できなぁE��チE��ワークに露出する可能性があります。露出したダチE��ュボ�Eド、認証なし�Ekubelet、�E開アクセス可能なAPIサーバ�Eは一般皁E��攻撁E�Eクトルです、E/p>
露出したKubernetesコンポ�Eネント�E、クラスタ管琁E��の直接アクセスを提供します。認証なし�Ekubelet APIはコンチE��実行を許可します。デフォルト認証惁E��を持つ露出したダチE��ュボ�Eド�E、cluster-adminアクセスを付与します。�E開etcdアクセスは、シークレチE��を含むすべてのクラスタチE�Eタを露出します、E/p>
# Kubernetes Dashboard exposed via LoadBalancer apiVersion: v1 kind: Service metadata: name: kubernetes-dashboard namespace: kubernetes-dashboard spec: type: LoadBalancer # Public internet access! ports: - port: 443 targetPort: 8443 selector: k8s-app: kubernetes-dashboard # Dashboard bound to cluster-admin service account # No authentication required Efull cluster access!
# Dashboard accessible only via kubectl proxy apiVersion: v1 kind: Service metadata: name: kubernetes-dashboard namespace: kubernetes-dashboard spec: type: ClusterIP # Internal only ports: - port: 443 targetPort: 8443 selector: k8s-app: kubernetes-dashboard --- # Access via: kubectl proxy, then browse to: # http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ # Or use kubectl port-forward for secure access
Kubernetesクラスタは多くのコンポ�Eネントで構�EされてぁE��ぁE APIサーバ�E、etcd、kubelet、kube-proxy、CoreDNS、サードパーチE��アドオン(Ingressコントローラ、サービスメチE��ュ、モニタリング)。設定ミスのある、また�Eパッチ未適用のコンポ�Eネント�E脁E��性を招きます。デフォルト設定�E多くの場合強化されてぁE��せん、E/p>
脁E��なクラスタコンポ�Eネント�E、リモートコード実行、権限�E格、また�Eサービス拒否のために悪用される可能性があります。kubelet、Ingressコントローラ、また�ECNIプラグインのCVEは、コンチE��エスケープとクラスタ乗っ取りにつながる可能性があります。時代遁E��のコンポ�Eネント�E既知の脁E��性を蓄積します、E/p>
# kubelet with insecure configuration # /var/lib/kubelet/config.yaml apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration authentication: anonymous: enabled: true # Anyone can access kubelet API! webhook: enabled: false # No authorization! authorization: mode: AlwaysAllow # All requests permitted! readOnlyPort: 10255 # Unauthenticated read port open!
# Hardened kubelet configuration apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration authentication: anonymous: enabled: false # Deny anonymous access webhook: enabled: true # Use API server for auth x509: clientCAFile: /etc/kubernetes/pki/ca.crt authorization: mode: Webhook # API server authorizes requests readOnlyPort: 0 # Disable read-only port protectKernelDefaults: true eventRecordQPS: 5
クラウド環墁EAWS、GCP、Azure)で実行されるKubernetesクラスタは、クラウドメタチE�EタAPIとノ�Eドに付与されたIAMロールにアクセスできます。Podを侵害した攻撁E��E�E、これらを使用してクラスタからクラウドアカウントへ権限を昁E��し、S3バケチE��、データベ�Eス、その他�Eクラウドサービスにアクセスできます、E/p>
ノ�EドレベルのIAMロールは、そのノ�Eド上�EすべてのPodに継承されます。侵害されたPodは、メタチE�EタAPI(169.254.169.254)にクエリしてクラウド認証惁E��を取得し、ノードロールが許可するあらめE��クラウドリソースにアクセスできます。これにより、Kubernetesから庁E��E��クラウド環墁E��の横方向�E移動が可能になります、E/p>
# Node IAM role with excessive permissions resource "aws_iam_role_policy_attachment" "node_admin" { role = aws_iam_role.node_role.name policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess" # All pods on this node inherit admin access! } # No IMDS restrictions Eany pod can get node credentials # curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
# Use IAM Roles for Service Accounts (IRSA) resource "aws_iam_role" "app_role" { name = "my-app-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Federated = aws_iam_openid_connect_provider.eks.arn } Action = "sts:AssumeRoleWithWebIdentity" Condition = { StringEquals = { "${aws_iam_openid_connect_provider.eks.url}:sub" = "system:serviceaccount:my-ns:my-app" } } }] }) } # Pod-level scoped IAM via service account annotation # Only this specific pod gets these specific permissions
Kubernetesは褁E��の認証メカニズムをサポ�EトしてぁE��ぁE 証明書、トークン、OIDC、Webhook認証。破損した認証には、E��皁E��ークンの使用、kubeconfigファイルの共有、証明書のローチE�Eション不足、アイチE��チE��チE��プロバイダーとの統合失敗が含まれます。サービスアカウントトークンの自動�Eウント�E不忁E��な攻撁E��を生み出します、E/p>
盗まれたまた�E漏洩したkubeconfigファイルとサービスアカウントトークンは、クラスタへの直接アクセスを提供します。期限�EれにならなぁE��皁E��ークンは永続的なアクセスを与えます。集中化されたアイチE��チE��チE��管琁E��なければ、E��職したチ�Eムメンバ�Eのアクセス取り消しは困難でエラーが発生しめE��くなります、E/p>
# Static token file for API server authentication # /etc/kubernetes/token-auth-file.csv # token,user,uid,"groups" # abc123,admin,1,"system:masters" # Static token, never expires! # Pod with auto-mounted service account token apiVersion: v1 kind: Pod metadata: name: app spec: # automountServiceAccountToken defaults to true! # Token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token containers: - name: app image: myapp:latest # App doesn't need K8s API access but has a token anyway
# Disable auto-mounted token for pods that don't need API access apiVersion: v1 kind: ServiceAccount metadata: name: my-app namespace: my-app-ns automountServiceAccountToken: false # No auto-mount --- # For pods that need API access, use bound tokens with expiry apiVersion: v1 kind: Pod metadata: name: api-consumer spec: serviceAccountName: api-consumer-sa automountServiceAccountToken: false containers: - name: app image: myapp@sha256:abc123... volumeMounts: - name: token mountPath: /var/run/secrets/tokens readOnly: true volumes: - name: token projected: sources: - serviceAccountToken: expirationSeconds: 3600 # 1-hour expiry audience: api-server
KubernetesはAPIサーバ�Eリクエスト�E監査イベントを生�Eしますが、監査ログは無効化されてぁE��か、設定ミスが多くあります。適刁E��ログ記録と監視がなければ、不正なシークレチE��アクセス、RBAC変更、コンチE��エスケープなどの悪意ある活動�E検�Eされません。コンチE��とノ�EドレベルでのランタイムセキュリチE��監視が不可欠です、E/p>
監査ログがなければ、攻撁E��E�E検�Eされずに活動します。バチE��ドアサービスアカウント�E作�E、シークレチE��の抽出、ワークロード�E変更を記録なしで行えます。何が起こったか、いつ、誰によってかを判断する監査証跡がなぁE��合、インシチE��ト対応�E深刻に損なわれます、E/p>
# API server with no audit logging configured # kube-apiserver flags: # --audit-log-path="" # No audit log! # --audit-policy-file="" # No audit policy! # No runtime security monitoring # No alerting on suspicious activities # Container logs not collected centrally # Default log retention Elogs lost on pod restart
# Comprehensive audit policy apiVersion: audit.k8s.io/v1 kind: Policy rules: # Log all secret access at Metadata level - level: Metadata resources: - group: "" resources: ["secrets"] # Log RBAC changes at RequestResponse level - level: RequestResponse resources: - group: rbac.authorization.k8s.io resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"] # Log pod exec/attach (potential attacks) - level: Request resources: - group: "" resources: ["pods/exec", "pods/attach", "pods/portforward"] # Default: log at Metadata level - level: Metadata
| ID | 脁E��性 | 深刻度 | 主な対筁E/th> |
|---|---|---|---|
| K01 | 安�EでなぁE��ークロード設宁E/td> | Critical | 非root、読み取り専用FS、ケーパビリチE��削除、リソース制陁E/td> |
| K02 | 過度に寛容な認可設宁E/td> | Critical | Namespace-scoped RBAC、ワイルドカード禁止、バインチE��ング監査 |
| K03 | シークレチE��管琁E�E失敁E/td> | Critical | 外部シークレチE��、E��止状態�E暗号化、ファイルマウンチE/td> |
| K04 | ポリシー実施の欠妁E/td> | High | Pod Security Standards、Kyverno/OPA Gatekeeper |
| K05 | ネットワーク刁E��制御の欠妁E/td> | High | Default-deny NetworkPolicy、�EイクロセグメンチE�Eション |
| K06 | 過度に露出したコンポ�EネンチE/td> | High | ClusterIPサービス、kubectl proxy、ファイアウォールルール |
| K07 | 設定ミスと脁E��なクラスタコンポ�EネンチE/td> | High | CIS Benchmark、匿名認証無効化、パチE��管琁E/td> |
| K08 | クラスタからクラウドへの横方向移勁E/td> | Critical | IRSA/Workload Identity、メタチE�EタAPIブロチE��、IMDSv2 |
| K09 | 破損した認証メカニズム | Critical | OIDC統合、バウンドトークン、�E動�Eウント無効匁E/td> |
| K10 | 不十刁E��ログ記録と監要E/td> | Medium | 監査ログ、Falco/Tetragon、SIEM統吁E/td> |