什么是 OWASP Kubernetes Top 10?

OWASP Kubernetes Top 10 确定了 Kubernetes 环境中最重要的安全风险。Kubernetes 已成为容器协调的事实标准,但其灵活性和复杂性带来了众多安全挑战。本指南涵盖工作负载错误配置、RBAC 问题、机密管理、网络分段等内容。

1️⃣ K01 - 不安全的工作负载配置

Critical

概述

不安全的工作负载配置是最常见的 Kubernetes 安全问题。以 root 身份运行的容器、权限过高、可写文件系统或无资源限制,都会造成严重的攻击。默认配置通常不安全,必须明确加固。

风险

拥有 root 权限和主机访问权限的受攻击容器可以逃出容器沙盒,访问主机文件系统,并转向其他工作负载。通过配置错误的 pod 进行权限升级可能会导致整个群集受损。

漏洞代码示例

YAML (Kubernetes Pod) ❌ Bad
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!

安全代码示例

YAML (Kubernetes Pod) ✅ Good
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"

缓解措施清单

2️⃣ K02 - 过度许可的授权配置

Critical

概述

Kubernetes RBAC(基于角色的访问控制)功能强大,但也很复杂。过度放任的角色,尤其是集群管理员绑定、通配符权限和过多的服务账户权限,会导致对集群资源、机密和工作负载的未经授权访问。

风险

获得超权限服务账户访问权限的攻击者可以列出机密、创建权限 pod、修改部署并升级为集群管理员。通配符 RBAC 规则相当于 Kubernetes 授予 root 访问权限。

漏洞代码示例

YAML (Kubernetes RBAC) ❌ Bad
# 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

安全代码示例

YAML (Kubernetes RBAC) ✅ Good
# 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

缓解措施清单

3️⃣ K03 - 秘密管理失败

Critical

概述

Kubernetes Secrets 默认只采用 base64 编码,而非加密。将敏感数据(API 密钥、数据库密码、TLS 证书)存储在纯配置映射、环境变量或未加密的 "秘密 "中,会暴露给拥有 API 访问权限的任何人。如果未启用静态加密,则 Secrets 在 etcd 中也是可见的。

风险

暴露的机密允许攻击者访问数据库、云账户和外部服务。未经加密存储在 etcd 中的秘密可被拥有 etcd 访问权限的任何人读取。环境变量机密在 pod 规格和进程列表中可见。

漏洞代码示例

YAML (Kubernetes) ❌ Bad
# Secret in plain ConfigMap — visible 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!

安全代码示例

YAML (Kubernetes + External Secrets) ✅ Good
# 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

缓解措施清单

4️⃣ K04 - 缺乏群集级的政策执行

High

概述

如果没有集群级策略,就无法防止部署不安全的工作负载。Pod 安全标准 (PSS)、准入控制器和 OPA Gatekeeper 或 Kyverno 等策略引擎对于在所有命名空间执行安全基线至关重要。

风险

如果不执行策略,任何开发人员都可以部署有权限的容器、使用 hostPath 卷或禁用安全控制。一个配置错误的工作负载就可能危及整个群集。手动审查无法涵盖所有违规行为。

漏洞代码示例

Bash ❌ Bad
#!/bin/bash
# No admission control — any 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 — now has host root access!

安全代码示例

YAML (Kyverno ClusterPolicy) ✅ Good
# 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

缓解措施清单

5️⃣ K05 - 网络分段控制缺失

High

概述

默认情况下,Kubernetes 集群中的所有 pod 都可以相互通信,不受任何限制。这种扁平化网络架构意味着,受到攻击的 pod 可以访问任何其他 pod、服务,甚至是 Kubernetes API 服务器。网络策略对实施微分区至关重要。

风险

没有网络分段,横向移动就变得微不足道。被入侵的前端 pod 可以直接访问后端数据库、内部服务和元数据 API(169.254.169.254)。这违反了网络层的最小权限原则。

漏洞代码示例

YAML (Kubernetes) ❌ Bad
# No NetworkPolicy — all 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

安全代码示例

YAML (Kubernetes NetworkPolicy) ✅ Good
# 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

缓解措施清单

6️⃣ K06 - Kubernetes 组件过度暴露

High

概述

Kubernetes 控制平面组件(API 服务器、etcd、kubelet、仪表盘)和应用服务可能会无意中暴露在互联网或不受信任的网络中。暴露的仪表盘、未经验证的 kubelet 和可公开访问的 API 服务器是常见的攻击载体。

风险

公开的 Kubernetes 组件可直接访问群集管理。未经验证的 kubelet API 允许执行容器。带有默认凭据的公开仪表盘可授予集群管理员访问权限。公共 etcd 访问可公开包括机密在内的所有集群数据。

漏洞代码示例

YAML (Kubernetes Service) ❌ Bad
# 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 — full cluster access!

安全代码示例

YAML (Kubernetes) ✅ Good
# 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

缓解措施清单

7️⃣ K07 - 配置错误和易受攻击的群集组件

High

概述

Kubernetes 集群由许多组件组成:API 服务器、etcd、kubelet、kube-proxy、CoreDNS 和第三方附加组件(入口控制器、服务网格、监控)。配置错误或未打补丁的组件会带来漏洞。默认配置通常没有加固。

风险

存在漏洞的群集组件可被利用来远程执行代码、权限升级或拒绝服务。kubelet、Ingress 控制器或 CNI 插件中的 CVE 可导致容器逃脱和群集接管。过时组件会积累已知漏洞。

漏洞代码示例

YAML (Kubernetes) ❌ Bad
# 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!

安全代码示例

YAML (Kubernetes) ✅ Good
# 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

缓解措施清单

8️⃣ K08 - 簇到云的横向移动

Critical

概述

在云环境(AWS、GCP、Azure)中运行的 Kubernetes 群集可以访问云元数据 API 和附加到节点的 IAM 角色。入侵 pod 的攻击者可以利用这些权限从群集升级到云账户,访问 S3 桶、数据库和其他云服务。

风险

节点级 IAM 角色由该节点上的所有 pod 继承。受损的 pod 可以查询元数据 API(169.254.169.254)以获取云凭证,然后访问节点角色允许的任何云资源。这样就能从 Kubernetes 横向移动到更广泛的云环境。

漏洞代码示例

Terraform (AWS EKS) ❌ Bad
# 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 — any pod can get node credentials
# curl http://169.254.169.254/latest/meta-data/iam/security-credentials/

安全代码示例

Terraform (AWS EKS with IRSA) ✅ Good
# 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

缓解措施清单

9️⃣ K09 - 破损的身份验证机制

Critical

概述

Kubernetes 支持多种身份验证机制:证书、令牌、OIDC 和 webhook 身份验证。失效的身份验证包括使用静态令牌、共享 kubeconfig 文件、不轮换证书以及未能与身份提供商集成。服务帐户令牌自动挂载会产生不必要的攻击面。

风险

被盗或泄漏的 kubeconfig 文件和服务帐户令牌可提供直接的群集访问权限。永不过期的静态令牌可提供持久访问权限。如果没有集中式身份管理,撤销已离职团队成员的访问权限既困难又容易出错。

漏洞代码示例

YAML (Kubernetes) ❌ Bad
# 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

安全代码示例

YAML (Kubernetes) ✅ Good
# 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

缓解措施清单

🔟 K10 - 记录和监控不足

Medium

概述

Kubernetes 会为 API 服务器请求生成审计事件,但审计日志经常被禁用或配置错误。如果没有适当的日志记录和监控,恶意活动(如未经授权的秘密访问、RBAC 更改和容器逃逸)就不会被发现。容器和节点级别的运行时安全监控至关重要。

风险

没有审计日志,攻击者的行动就不会被发现。他们可以在没有任何记录的情况下创建后门服务账户、提取机密和修改工作负载。如果没有审计跟踪来确定发生了什么、何时发生、由谁发生,事件响应就会受到严重影响。

漏洞代码示例

YAML (Kubernetes) ❌ Bad
# 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 — logs lost on pod restart

安全代码示例

YAML (Kubernetes Audit Policy) ✅ Good
# 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

缓解措施清单

📊 汇总表

身份证 脆弱性 严重性 关键缓解措施
K01不安全的工作负载配置Critical非根目录、只读 FS、删除功能、资源限制
K02过于放任的授权Critical名称空间范围的 RBAC,无通配符,审计绑定
K03秘密管理失败Critical外部机密、静态加密、文件挂载
K04政策执行不力HighPod 安全标准,Kyverno/OPA Gatekeeper
K05缺失的网络分割High默认-拒绝网络策略,微分段
K06过度暴露的组件HighClusterIP 服务、kubectl 代理、防火墙规则
K07配置错误的群集组件HighCIS 基准、禁用匿名验证、补丁管理
K08云团到云团的横向移动CriticalIRSA/Workload Identity、块元数据 API、IMDSv2
K09被破坏的验证机制CriticalOIDC 集成、绑定令牌、禁用自动安装
K10日志记录和监控不足Medium审计日志、Falco/Tetragon、SIEM 集成