从 runC 容器逃逸漏洞 CVE-2025-52881 分析:如何防御绕过 LSM 的高危攻击

枫少@KillBoy
枫少@KillBoy
枫少@KillBoy
管理员
273
文章
0
粉丝
云原生安全17264字数 3599阅读11分59秒阅读模式
AI智能摘要
AI 生成的文章内容摘要

CVE-2025-52881 的风险不在于容器进程单纯获得了某个额外权限,而在于 runC 在处理容器初始化阶段的 /proc 写入时,可能被攻击者利用竞态条件和共享挂载改变实际写入目标。这样一来,原本用于设置 LSM 进程安全标签的写操作,就可能被重定向到其他 procfs 文件,进一步造成宿主机拒绝服务,甚至形成容器逃逸。对使用 Docker、containerd、CRI-O 或 Kubernetes 的环境而言,真正需要核查的是底层 runC 版本、共享挂载策略,以及宿主机内核对敏感 procfs 接口的暴露程度。

云原生容器运行时与 Linux 内核安全排查示意

漏洞影响:LSM 标签写入被重新定向

runC 负责按照 OCI 规范创建和启动容器,期间会配置命名空间、根文件系统、挂载点以及容器初始进程。对于启用了 SELinux 或其他 LSM 机制的系统,runC 还需要通过 /proc/self/attr/ 相关接口为容器进程设置安全标签。这个步骤决定了进程后续受到哪些访问控制规则约束。

CVE-2025-52881 的核心问题,是攻击者可以利用一个带有共享挂载的竞态容器,干扰 runC 对 /proc 路径的解析和写入。公开资料显示,受影响的 runC 版本包括 1.2.7、1.3.2 和 1.4.0-rc.2,修复版本分别为 1.2.8、1.3.3 和 1.4.0-rc.3。

攻击者不一定需要直接修改宿主机文件。更现实的路径是让 runC 以为自己正在向容器进程的 LSM 属性文件写入标签,但在实际写入时,路径已经通过符号链接、共享挂载或其他路径重定向机制指向了不同的 procfs 文件。这样会产生两个后果:

  • LSM 标签没有按预期应用,容器进程可能失去原本的安全约束;
  • 写入内容可能进入具有副作用的内核接口,造成宿主机拒绝服务或进一步的权限边界突破。

这也是该漏洞与普通容器内权限提升问题的区别:攻击的关键目标不是直接利用容器中的某个业务进程,而是干扰 runC 代表宿主机执行的初始化操作。

/proc/self/attr/ 为什么是关键位置

/proc/self/attr/ 并不是普通的配置目录。它由内核提供,用于访问当前进程相关的安全属性,LSM 框架可以通过其中的接口读取或设置进程标签。runC 在启动容器时,需要在合适的时机向这些接口写入标签,使容器进程受到 SELinux 等安全策略的约束。

早期相关漏洞的修复思路,主要是确认目标确实属于 procfs,避免攻击者把 /proc/self/attr/ 替换成一个普通的 tmpfs 文件。CVE-2025-52881 表明,仅验证“目标是不是 procfs”仍然不够。攻击者可以让该路径指向另一个真实的 procfs 文件,例如一个写入后没有明显效果的接口,从而绕过这种有限检查。

这类绕过的危险在于,文件类型检查和路径安全检查解决的不是同一个问题:

  • 文件类型检查回答的是“目标是否来自 procfs”;
  • 路径完整性检查回答的是“目标是否仍然是预期的 LSM 属性接口”;
  • 语义安全检查回答的是“该写入是否可能触发其他内核行为”。

如果只完成第一层检查,攻击者仍可能利用路径竞态和链接跟随,把写入操作导向其他内核接口。

竞态、共享挂载与 procfs 重定向

该漏洞依赖的攻击条件与共享挂载密切相关。攻击者需要构造或控制一个能够影响路径解析的容器环境,使 runC 在检查路径和真正执行写入之间出现状态变化。公开资料将其归类为竞态条件和符号链接跟随问题,并指出,带有自定义共享挂载的并行容器执行场景也可能成为触发条件。

从防守角度看,风险链条可以概括为:

  1. 攻击者影响容器中的挂载或路径布局;
  2. runC 访问用于设置 LSM 标签的 /proc/self/attr/
  3. 在路径检查与写入之间,目标被切换或重定向;
  4. runC 将原本的安全标签写入操作发送到其他 procfs 文件;
  5. 被选中的接口产生拒绝服务、内核状态改变或进一步的逃逸条件。

这里的“共享挂载”不只意味着管理员显式配置了某个宿主机目录。构建、启动和编排流程中,只要允许容器之间共享特定挂载,或者让不可信工作负载参与并行容器操作,就应当重新评估路径解析是否可能受到影响。

/proc/sysrq-trigger 的作用与风险边界

/proc/sysrq-triggerlinux 提供的 Magic SysRq 触发接口。具备相应权限的进程向该接口写入特定控制字符后,可以请求内核执行紧急系统操作。具体可用动作取决于内核配置、权限控制和系统状态,可能涉及同步磁盘、终止任务、触发内核崩溃等高影响行为。

在 CVE-2025-52881 的语境中,/proc/sysrq-trigger 应被视为一种高价值的 procfs 写入目标:如果 runC 的写操作能够被重定向到该接口,攻击者就可能把一次本应设置 LSM 标签的操作,转化为影响宿主机可用性的内核控制操作。最直接的风险是拒绝服务,严重时可能使节点重启、崩溃或失去对工作负载的管理能力。

但这并不意味着漏洞在所有环境中都会自动通过 sysrq-trigger 导致崩溃。实际影响还取决于以下因素:

  • 宿主机内核是否启用了相应的 SysRq 行为;
  • 容器进程是否具备足以触发该接口的权限;
  • 运行时和内核是否对该路径实施了额外限制;
  • 被重定向的写入内容是否能被该接口解释为有效操作。

因此,排查时不应只问“容器能不能访问这个路径”,还要确认该路径是否被映射、暴露或间接影响,以及写入动作是否可能跨越容器的权限边界。

core_pattern 为什么可能扩大影响

/proc/sys/kernel/core_pattern 用于控制进程发生崩溃时核心转储的命名方式和处理方式。在某些配置下,它可以把核心转储交给一个外部处理程序,内核随后按照该配置执行相应的转储处理流程。

如果攻击者能够通过 procfs 写入重定向修改 core_pattern,风险就不再局限于一次标签设置失败。后续宿主机上的进程崩溃可能触发被篡改的核心转储处理逻辑,从而带来信息泄露、拒绝服务,或者在特定权限和内核配置组合下造成更严重的宿主机影响。

需要强调的是,core_pattern 的危险依赖多个条件:系统是否启用核心转储、是否使用管道式处理方式、处理程序运行时具有什么权限,以及容器对宿主机进程和文件系统的可见范围。它不是一个“写入后必然完成宿主机代码执行”的开关,但属于必须纳入审计的高敏感内核接口。

在生产环境中,core_pattern 应被当作宿主机级配置保护,而不是普通容器运行参数。尤其要避免让不可信工作负载拥有修改这类内核控制项的间接路径,并在节点基线中记录其期望状态,防止发生静默篡改。

生产环境的首要防御:升级 runC 及其上层组件

最有效的修复措施是将 runC 升级到包含补丁的版本:

  • 1.2.7 升级到 1.2.8 或更高版本;
  • 1.3.2 升级到 1.3.3 或更高版本;
  • 1.4.0-rc.2 升级到 1.4.0-rc.3 或更高版本。

实际环境中,管理员通常不会直接手工调用 runC,而是通过 containerd、CRI-O、Docker 或云厂商提供的 Kubernetes 节点镜像间接使用它。因此,不能只查看业务容器镜像版本,也不能只查看客户端版本,而应从节点上确认实际运行时所携带的 runC 版本。

升级时建议按以下顺序核对:

  1. 识别集群节点使用的容器运行时及其安装来源;
  2. 确认节点实际调用的 runC 版本,而不是仅查看软件仓库中的可用版本;
  3. 检查上层运行时是否已经发布包含修复的更新;
  4. 在预生产节点验证容器启动、镜像构建和共享挂载相关工作流;
  5. 分批替换节点,避免一次性重启影响整个集群;
  6. 升级后重新确认节点基线和容器运行时版本。

对于托管 Kubernetes,平台公告中的“已修复”通常只代表特定节点镜像或运行时组合已经处理,仍应确认自身节点池是否完成滚动更新。自建集群则需要把 runC、containerd 或 CRI-O 的更新纳入节点补丁流程,不能只等待应用镜像重新发布。

内核和容器配置的加固重点

运行时升级解决的是漏洞本身,内核加固解决的是即使出现运行时缺陷,也尽量降低其影响范围。两者不能互相替代。

首先,应减少不可信容器接触宿主机敏感接口的机会。生产工作负载应坚持最小权限原则,避免使用特权容器,谨慎授予额外 linux capabilities,并限制宿主机目录、设备和进程命名空间的共享。尤其要审查能够改变挂载视图的配置,因为本漏洞的触发条件与共享挂载和路径重定向直接相关。

其次,应对 /proc 采用更严格的挂载和可见性策略。容器不应获得不必要的宿主机 procfs 视图,也不应通过共享挂载把宿主机敏感路径暴露给工作负载。对于必须使用共享挂载的构建任务,应将其与普通业务 Pod 隔离,限制可提交的构建内容和运行权限。

再次,要把以下接口纳入节点安全基线:

  • /proc/sysrq-trigger:确认容器和非特权服务无法直接或间接写入;
  • core_pattern:记录期望配置,监控异常变化,并限制核心转储处理程序的权限;
  • /proc/self/attr/:确认运行时能够正常设置 LSM 标签,避免被异常挂载或链接结构干扰;
  • LSM 状态:确认 SELinux 或其他适用的强制访问控制机制处于预期状态,而不是因为容器启动失败或节点配置变更被动降级。

如果系统启用了 SELinux,应重点确认容器进程实际获得了预期标签,并检查异常容器是否出现标签缺失、标签变化或启动阶段安全属性写入失败。安全标签不是“配置成功就永远有效”,而是应当纳入节点和工作负载的持续核验。

如何评估自身集群是否暴露

风险评估可以围绕运行时、权限和挂载三条线展开。

运行时层面,先盘点所有 Kubernetes 节点、构建节点和独立 Docker 主机的 runC 版本,特别关注版本处于 1.2.7、1.3.2 或 1.4.0-rc.2 的节点。若无法确认实际版本,应按未修复处理,直到完成节点级验证。

权限层面,检查是否存在特权容器、过度授予 capabilities、宿主机 PID 或网络命名空间共享,以及允许不可信用户提交任意构建任务的流水线。这些配置未必单独构成漏洞利用条件,但会显著扩大 procfs 重定向后的影响范围。

挂载层面,重点查看容器是否使用宿主机目录、共享 tmpfs、可变挂载结构或构建过程中产生的自定义共享挂载。对于必须保留的共享挂载,应明确其来源、读写属性、生命周期和可提交者范围,避免把高权限构建工作负载与普通租户混在同一节点。

监控层面,可以关注节点上异常的容器并行启动、运行时错误、LSM 标签设置失败、core_pattern 或 SysRq 相关配置变化,以及节点无明显原因的崩溃和重启。单条日志通常不足以确认攻击,但多个信号同时出现时,应优先隔离节点并保存运行时、内核和审计信息。

发现疑似利用后的处置

如果怀疑节点已经受到利用,不应只删除相关 Pod。首先应停止继续调度不可信工作负载,将节点从集群中隔离,并保留运行时日志、内核日志、审计记录和节点配置快照。随后核对 runC、containerd 或其他运行时版本,以及 LSM 状态、敏感 procfs 配置和近期挂载变化。

对于已经发生异常重启、内核崩溃或安全标签缺失的节点,最好按照节点不再可信的标准处理,而不是仅重新启动服务。完成运行时和内核修复后,应重新创建节点或至少执行完整的节点重置,避免攻击者留下的挂载、进程或配置影响后续工作负载。

CVE-2025-52881 的防御重点很明确:先修复 runC,再收紧共享挂载和容器权限,同时保护 /proc/sysrq-triggercore_pattern 以及 LSM 相关接口。只要仍有未修复的运行时节点,或者无法确认节点上的实际 runC 版本,就不应把容器隔离视为可靠的宿主机边界。

Kubernetes 节点与容器运行时安全加固场景

 
枫少@KillBoy
  • it2021
  • it2021.com
  • 代码执行
  • 漏洞利用
  • 访问控制
评论  17  访客  17
    • 废土秃鹫
      废土秃鹫 2

      先查节点上的实际runC版本更稳妥

      • 已离线勿扰
        已离线勿扰 0

        共享挂载这类配置确实容易被忽略

        • 狂野鬣狗
          狂野鬣狗 0

          容器隔离边界还是不能只看镜像权限

          • 谨慎周密派
            谨慎周密派 1

            想知道托管集群一般怎么确认节点已更新

              • 生活诗人
                生活诗人 1

                @ 谨慎周密派 可以对照节点池镜像版本和实际运行时,再抽查几台确认

              • 叛逆小魔王
                叛逆小魔王 1

                LSM标签异常应该纳入日常监控了

                • 小绵羊糖
                  小绵羊糖 1

                  构建节点和业务节点最好彻底分开

                    • 归鹤
                      归鹤 0

                      @ 小绵羊糖 这类任务权限和挂载更复杂,混在一起确实不好控

                    • 梦境之茧
                      梦境之茧 1

                      / proc接口的风险比想象中更复杂

                      • 高音
                        高音 1

                        特权容器确实该尽量从生产环境移除

                          • 藕榭仙子
                            藕榭仙子 1

                            @ 高音 是的,尤其要盯住能接触宿主机设备和挂载的工作负载

                          • 霭霭
                            霭霭 0

                            发现异常节点后只删Pod恐怕不够

                            • 猴小六
                              猴小六 0

                              core_pattern的基线监控很有必要

                              • 社恐小行星
                                社恐小行星 1

                                共享挂载最好记录来源、读写属性和生命周期

                                • 风语之森
                                  风语之森 1

                                  升级后分批滚动更稳妥,别一次重启整座集群

                                  • 风吟竹径
                                    风吟竹径 1

                                    别只看镜像版本,节点上的 runC 才是关键

                                    • 黑夜独行
                                      黑夜独行 2

                                      不确定实际版本时,按未修复节点处理比较保险

                                    匿名

                                    发表评论

                                    匿名网友

                                    拖动滑块以完成验证