#容器逃逸防护策略
本指南演示如何配置 Kyverno,通过阻止可能导致容器突破隔离边界的高风险容器配置,来防止容器逃逸攻击。
#目录
什么是容器逃逸防护?快速开始1. 阻止特权容器2. 测试策略核心容器逃逸防护策略策略 1:禁止访问宿主命名空间策略 2:禁止宿主路径挂载策略 3:禁止宿主端口策略 4:禁止危险能力策略 5:要求非 root 用户运行容器高级场景场景 1:环境特定策略场景 2:工作负载特定例外测试与验证测试特权容器测试宿主命名空间访问测试宿主路径挂载测试有效安全容器最佳实践1. 从审计模式开始2. 排除系统命名空间#什么是容器逃逸防护?
容器逃逸防护涉及检测并阻止危险的容器配置,这些配置可能允许攻击者逃离容器隔离并访问宿主系统。包括:
- 特权容器:以提升权限运行的容器
- 宿主命名空间访问:容器共享宿主的 PID、网络或 IPC 命名空间
- 宿主路径挂载:容器挂载宿主文件系统路径
- 危险能力:容器拥有过多的 Linux 能力
- 宿主端口访问:容器绑定宿主网络端口
#快速开始
#1. 阻止特权容器
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
annotations:
policies.kyverno.io/title: Disallow Privileged Containers
policies.kyverno.io/category: Pod Security Standards (Baseline)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Privileged mode disables most security mechanisms and must not be allowed.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: privileged-containers
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Privileged mode is disallowed. The fields spec.containers[*].securityContext.privileged,
spec.initContainers[*].securityContext.privileged, and spec.ephemeralContainers[*].securityContext.privileged
must be unset or set to false.
pattern:
spec:
=(ephemeralContainers):
- =(securityContext):
=(privileged): "false"
=(initContainers):
- =(securityContext):
=(privileged): "false"
containers:
- =(securityContext):
=(privileged): "false"#2. 测试策略
# 应用策略
kubectl apply -f disallow-privileged-containers.yaml
# 尝试创建特权容器(应失败)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-privileged
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
EOF
# 尝试创建普通容器(应成功)
kubectl run test-normal --image=nginx
# 清理
kubectl delete pod test-privileged test-normal --ignore-not-found#核心容器逃逸防护策略
#策略 1:禁止访问宿主命名空间
防止容器访问宿主命名空间:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-namespaces
annotations:
policies.kyverno.io/title: Disallow Host Namespaces
policies.kyverno.io/category: Pod Security Standards (Baseline)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Host namespaces (Process ID namespace, Inter-Process Communication namespace, and
network namespace) allow access to shared information and can be used to elevate
privileges. Pods should not be allowed access to host namespaces.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: host-namespaces
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Sharing the host namespaces is disallowed. The fields spec.hostNetwork,
spec.hostIPC, and spec.hostPID must be unset or set to false.
pattern:
spec:
=(hostPID): "false"
=(hostIPC): "false"
=(hostNetwork): "false"#策略 2:禁止宿主路径挂载
阻止容器挂载宿主文件系统路径:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path
annotations:
policies.kyverno.io/title: Disallow Host Path
policies.kyverno.io/category: Pod Security Standards (Baseline)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod,Volume
policies.kyverno.io/description: >-
HostPath volumes let Pods use host directories and volumes in containers.
Using host resources can be used to access shared data or escalate privileges
and should not be allowed.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
HostPath volumes are forbidden. The field spec.volumes[*].hostPath must be unset.
pattern:
spec:
=(volumes):
- X(hostPath): "null"#策略 3:禁止宿主端口
防止容器绑定宿主网络端口:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-ports
annotations:
policies.kyverno.io/title: Disallow Host Ports
policies.kyverno.io/category: Pod Security Standards (Baseline)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Access to host ports allows potential snooping of network traffic and should not be
allowed, or at minimum restricted to a known list.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: host-ports-none
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Use of host ports is disallowed. The fields spec.containers[*].ports[*].hostPort,
spec.initContainers[*].ports[*].hostPort, and spec.ephemeralContainers[*].ports[*].hostPort
must either be unset or set to 0.
pattern:
spec:
=(ephemeralContainers):
- =(ports):
- =(hostPort): 0
=(initContainers):
- =(ports):
- =(hostPort): 0
containers:
- =(ports):
- =(hostPort): 0#策略 4:禁止危险能力
阻止容器添加危险的 Linux 能力:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-capabilities-strict
annotations:
policies.kyverno.io/title: Disallow Capabilities (Strict)
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Adding capabilities other than `NET_BIND_SERVICE` is disallowed. In addition,
all containers must explicitly drop `ALL` capabilities.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-drop-all
match:
any:
- resources:
kinds:
- Pod
preconditions:
all:
- key: "{{ request.operation || 'BACKGROUND' }}"
operator: NotEquals
value: DELETE
validate:
message: >-
Containers must drop `ALL` capabilities.
foreach:
- list: request.object.spec.[ephemeralContainers, initContainers, containers][]
deny:
conditions:
all:
- key: ALL
operator: AnyNotIn
value: "{{ element.securityContext.capabilities.drop || `[]` }}"
- name: adding-capabilities
match:
any:
- resources:
kinds:
- Pod
preconditions:
all:
- key: "{{ request.operation || 'BACKGROUND' }}"
operator: NotEquals
value: DELETE
validate:
message: >-
Any capabilities added other than NET_BIND_SERVICE are disallowed.
foreach:
- list: request.object.spec.[ephemeralContainers, initContainers, containers][]
deny:
conditions:
any:
- key: "{{ element.securityContext.capabilities.add || `[]` }}"
operator: AnyNotIn
value:
- NET_BIND_SERVICE#策略 5:要求非 root 用户运行容器
确保容器以非 root 用户身份运行:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-run-as-nonroot
annotations:
policies.kyverno.io/title: Require Run As Non-Root User
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Containers must run as a non-root user. This policy ensures runAsNonRoot is set to true.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: run-as-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Running as root is not allowed. Either the field spec.securityContext.runAsNonRoot
must be set to true, or the field spec.containers[*].securityContext.runAsNonRoot
must be set to true.
anyPattern:
- spec:
securityContext:
runAsNonRoot: "true"
- spec:
containers:
- securityContext:
runAsNonRoot: "true"#高级场景
#场景 1:环境特定策略
针对不同环境设置不同安全级别:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: environment-container-security
spec:
validationFailureAction: Enforce
background: true
rules:
# 生产环境:严格安全
- name: production-strict-security
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
- prod-*
validate:
message: "Production environments require strict container security"
pattern:
spec:
=(hostPID): "false"
=(hostIPC): "false"
=(hostNetwork): "false"
securityContext:
runAsNonRoot: "true"
containers:
- securityContext:
privileged: "false"
runAsNonRoot: "true"
capabilities:
drop:
- ALL
# 开发环境:更宽松但仍安全
- name: development-basic-security
match:
any:
- resources:
kinds:
- Pod
namespaces:
- development
- dev-*
- staging
validate:
message: "Development environments require basic container security"
pattern:
spec:
=(hostPID): "false"
=(hostIPC): "false"
containers:
- securityContext:
=(privileged): "false"#场景 2:工作负载特定例外
允许特定工作负载的受控例外:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: workload-specific-security
spec:
validationFailureAction: Enforce
background: true
rules:
- name: system-workloads-exception
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
- resources:
kinds:
- Pod
names:
- "monitoring-*"
- "logging-*"
validate:
message: "Container security policies apply to application workloads"
pattern:
spec:
=(hostNetwork): "false"
containers:
- securityContext:
=(privileged): "false"#测试与验证
#测试特权容器
# 应该被阻止
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-privileged
spec:
containers:
- name: test
image: nginx
securityContext:
privileged: true
EOF#测试宿主命名空间访问
# 应该被阻止
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-host-network
spec:
hostNetwork: true
containers:
- name: test
image: nginx
EOF#测试宿主路径挂载
# 应该被阻止
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
containers:
- name: test
image: nginx
volumeMounts:
- name: host-vol
mountPath: /host
volumes:
- name: host-vol
hostPath:
path: /
EOF#测试有效安全容器
# 应该被允许
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-secure
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
containers:
- name: test
image: nginx
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
EOF#最佳实践
#1. 从审计模式开始
spec:
validationFailureAction: Audit # 先以警告模式启动,不阻止#2. 排除系统命名空间
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
- kube-public