在 Linux 容器技术普及之后,系统权限管理出现了一个新的攻击面:默认容器往往携带几十种内核 capabilities,而多数应用只用到其中少数几个。把不必要的特权收掉,是降低容器逃逸风险最直接有效的手段。下面从原理、配置到验证逐步说明能力削减该怎么做。

理解 Linux capabilities 与容器默认授权模型
传统 Linux 用超级用户 root 和普通用户二分法控制权限,但这种粗粒度模型在容器场景里非常危险。内核后来引入了 capabilities 机制,把 root 的特权拆成如 CHOWN、NET_BIND_SERVICE、SYS_ADMIN 等独立单元。普通进程若拥有某 capability,就能执行对应特权操作,而不必是整个 root。
容器运行时为了兼容性与易用性,通常给容器一个删减版但仍较完整的 capability 集合。以 Docker 为例,默认保留约十四个能力,其中包含 SYS_MODULE、NET_RAW 这类明显超出一般 Web 服务需要的项。攻击者若在容器内拿到执行权限,便可利用 NET_RAW 制造原始套接字包,或用 SYS_ADMIN 挂载文件系统,进一步渗透宿主机。因此能力削减的第一要务是弄清应用真正依赖哪些能力。
识别依赖项不能只靠猜。可以在保留默认能力的情况下用 strace 或审计日志观察系统调用,也可查阅中间件官方文档。例如 Nginx 仅需 NET_BIND_SERVICE 绑定 80 端口,若运行在非特权端口则连这个都不需要;而某些需要修改系统时间的服务才会用到 SYS_TIME。把清单列出来,削减才有依据。
在 Docker 与 Kubernetes 中实施 cap_drop 和 cap_add
Docker 提供 cap_drop 与 cap_add 指令,让用户在启动容器时显式删减或增补能力。最省事的做法是先 drop 掉 ALL,再按需 add 回来。比如一个只提供 HTTP 接口且监听高位端口的 Go 服务,可写成如下形式:
docker run --rm --cap-drop ALL --cap-add NET_BIND_SERVICE my-app:latest
上面命令先撤销全部默认能力,仅保留绑定特权端口一项。如果该服务改用 8080 端口,连 NET_BIND_SERVICE 也可去掉,实现近乎零特权的运行态。要注意 cap_add 只能加回被 drop 的或默认未给的合法项,写错名字会导致启动报错,所以配置后务必做一次冒烟测试。
在 Kubernetes 环境里,对应字段位于 Pod 的 securityContext。集群管理员还可以通过 PodSecurityPolicy 或较新的 Pod Security Standards 做全局约束。下面片段展示了一个只保留 CHOWN 与 SETUID 的容器上下文:
apiVersion: v1
kind: Pod
metadata:
name: demo
spec:
containers:
- name: app
image: my-app:latest
securityContext:
capabilities:
drop:
- ALL
add:
- CHOWN
- SETUID
这种声明式方式便于纳入 CI 校验,防止有人误提交宽松配置。同时建议配合 readOnlyRootFilesystem: true 与 runAsNonRoot: true,让能力削减不是单点防护,而是纵深防御的一环。需要提醒的是,某些 CNI 插件或监控 agent 可能依赖 NET_RAW,集群级 drop ALL 前要评估基础设施容器是否受影响。
削减后的功能验证与常见故障排查
能力去掉之后,首要任务是确认业务没被误伤。基础验证可在容器内执行原先依赖特权的操作,看是否返回 Operation not permitted。例如 drop 了 NET_RAW 后,运行 ping 通常会失败,这属预期行为;但若业务本身用原始套接字做健康检查,就要重新评估是否真需该能力或改用其他探测手段。
另一类隐蔽问题是动态库或语言运行时偷偷使用特权。比如带 CAP_SYS_ADMIN 的容器里,某些 Java 版本会尝试挂载 cgroup 以读取资源配额,削减后可能仅打警告而不崩溃,容易漏检。建议在预发环境用 Chaos 或权限审计工具扫描,并结合日志关键字如 permission denied 做告警。下表列出几种典型能力与移除后现象:
| Capability | 常见用途 | 移除后影响 |
|---|---|---|
| NET_RAW | 构造原始包、ping | 无法做 ICMP 探测,部分抓包工具失效 |
| SYS_ADMIN | 挂载、命名空间操作 | 多数应用无感,少数运行时配置读取异常 |
| NET_BIND_SERVICE | 绑定 1024 以下端口 | 低端口监听失败,需改高位端口 |
当排查陷入僵局时,可临时用 --cap-add ALL 恢复全量能力验证是否为削减所致,再逐步二分定位缺失项。生产环境推荐把最终 capability 清单写进镜像元数据或部署模板,形成组织内部的安全基线,避免不同团队重复踩坑。只要流程规范,能力削减并不会增加长期维护成本,反而让系统边界更清晰。
把能力削减纳入持续交付流水线
一次性的手工配置难以抵挡后续变更带来的权限膨胀。理想做法是把 cap_drop 规则作为镜像构建或 Helm 模板的强制字段,在代码评审阶段就拦截宽松设定。CI 任务里可调用 docker inspect 或 kubectl dry-run 输出,用脚本断言容器不带有 SYS_ADMIN 等高危能力。
此外,运行时防护组件如 Falco 能基于系统调用观测异常特权使用,即使配置被绕过也可兜底报警。将削减策略、镜像扫描、运行时监控三者串联,才能把 capabilities 最佳实践从文档真正落地为工程习惯。团队应定期回顾能力清单,随业务演进做减法而非加法。
capabilitiesLinux容器能力削减修改时间:2026-08-17 02:50:32