BlackHatUSA2026:Linux容器错误取反"

admin 2026-10-17 02:52:46 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

Black Hat USA 2026:Linux容器错误取反

原创

Max Luo
Max Luo

白帽子罗棋琛

2026年8月26日 08:18
广东

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

一个错误取反,如何击穿 Linux 与托管容器

Black Hat USA 2026 议题《!secure: A Single Wrong Negation to Root Linux and Escape Managed Kubernetes》课件解读。本文依据公开课件、Linux 修复提交与发行版公告整理,讨论 CVE-2026-23111 的根因、风险判断和防守落地;不复现完整利用代码。

安全团队经常把内核漏洞按“是否有竞态、是否能稳定提权、容器里是否可达”来分级。CVE-2026-23111 恰好把这三道筛选都绕了过去:它不依赖争抢时间窗,触发条件来自一次可重复的事务回滚;在允许非特权用户命名空间和 nf\_tables 的环境里,本地普通用户可以把引用计数稳定耗尽;而容器与宿主机共享内核,默认 Pod 也可能把同一原语带到节点上。

最值得复盘的不是后半段的堆布局,而是最前面的一个 !:一段看上去与 deactivate 路径“完全对称”的代码,实际破坏了 abort 必须恢复所有副作用的约束。

1、先看结论:这是事务一致性漏洞,不只是一个 UAF

漏洞位于 Linux Netfilter 的 nf\_tables 子系统,函数为 nft_map_catchall_activate()。公开修复只改了一个布尔判断:

diff

 static void nft_map_catchall_activate(...)  {      list_for_each_entry(catchall, &set->catchall_list, list) {          ext = nft_set_elem_ext(set, catchall->elem); -        if (!nft_set_elem_active(ext, genmask))+        if (nft_set_elem_active(ext, genmask))              continue;           nft_clear(ctx->net, ext);          nft_setelem_data_activate(ctx->net, set, &elem);      }  }

这行代码处在失败事务的回滚路径。删除 set 时,catch-all verdict element 会被暂时停用,并释放其指向 chain 的一次引用;如果同一批事务随后失败,abort 路径必须重新激活该元素,同时把引用补回来。

错误判断却跳过了 inactive 元素。结果不是“状态显示错了一下”,而是对象仍被引用、引用计数却少了一次。重复失败事务可把 chain->use 降到零,之后删除 chain 会释放对象,但 catch-all element 仍保留指向它的指针,由此形成 use-after-free。

Ubuntu 将 CVE-2026-23111 定为 High,CVSS 3.1 为 7.8,并明确描述为:在启用 CONFIG_USER_NS 和 CONFIG_NF_TABLES 的发行版上,非特权本地用户可通过 user namespace 与 nftables 实现提权。这个前提比“所有 Linux 都能打”精确得多。

2、为什么复制对称代码反而制造了错误

课件把 activate 与 deactivate 放在一起,对代码评审很有启发。

nft_set_elem_active() 的语义容易读反:genmask 对应位为 clear 时元素处于 active,函数返回 true;对应位为 set 时处于 inactive,函数返回 false。

c

/* 用命名变量展开,避免在条件中二次取反 */constbool is_active = nft_set_elem_active(ext, genmask);  /* deactivate:只处理 active 元素 */if (!is_active)     continue; deactivate_element(ext);  /* activate/rollback:只处理 inactive 元素 */if (is_active)     continue; activate_element(ext);

问题不只是开发者“少看了一个感叹号”。这里至少叠加了三种可维护性风险:

  • 函数名表达状态查询,底层实现却又对位掩码取反;
  • activate 与 deactivate 的循环骨架相似,复制后很容易保留同一条件;
  • 正常提交路径容易覆盖,失败事务的补偿路径却很少进入常规测试。

这类代码应按状态转换来审,而不是逐行看“像不像”。更稳妥的评审问题是:进入回滚前后,每个对象的 active 状态、引用计数和可达关系是否恢复为同一组不变量?

3、确定性来自“计数循环”,不是高超的竞态技巧

很多内核 UAF 需要让释放与重用在很窄的时间窗相遇。这个漏洞的第一阶段不同:每次构造“先删除 set、后让批事务失败”的序列,回滚就稳定漏掉一次引用恢复。攻击者不是等待概率,而是在执行一个有限循环。

可以把根因抽象成下面的状态机。这里故意不保留真实 Netlink 消息细节,只展示防守方需要验证的不变量:

python

from dataclasses import dataclass  @dataclassclassModel:     element_active: bool = True     chain_refs: int = 1defprepare_delete(m: Model) -> None:     assert m.element_active and m.chain_refs > 0     m.element_active = False     m.chain_refs -= 1defabort_delete(m: Model) -> None:     # 正确回滚:inactive 元素必须重新激活并恢复引用if m.element_active:         return     m.element_active = True     m.chain_refs += 1definvariant(m: Model) -> None:     # 仍有活动元素指向 chain 时,引用数不能为零if m.element_active:         assert m.chain_refs >= 1deftest_abort_is_idempotent() -> None:     m = Model()     before = Model(m.element_active, m.chain_refs)     for _ inrange(1000):         prepare_delete(m)         abort_delete(m)         invariant(m)         assert m == before

这个测试比“执行一次删除是否成功”有价值,因为它直接检查重复 abort 后的守恒关系。课件展示的 UAF 时间线本质上就是这条不变量被破坏后的对象生命周期。

4、为什么普通用户和默认 Pod 能碰到内核 Netfilter

漏洞可利用性取决于入口是否可达。普通进程通常没有宿主网络命名空间里的 CAP_NET_ADMIN,但某些发行版允许非特权用户创建 user namespace,再在新的 network namespace 中获得相对于该 namespace 的管理能力。这样,进程便可能合法调用 nf\_tables 接口。

容器场景也不能只看 Pod spec 中有没有 privileged: true。需要同时回答四个问题:

  1. 容器的 seccomp profile 是否允许创建相关 namespace 的系统调用;
  2. 节点是否允许非特权 user namespace;
  3. 容器进程能否到达 nf\_tables 所需的内核配置和模块;
  4. 节点实际运行的 kernel flavor 是否已经包含修复。

课件中的攻击模型是“已取得普通 Pod 内代码执行”,而不是从互联网直接打节点,也不是只凭创建一个 Pod 就自动逃逸。

可以用准入策略先压缩明显不必要的 namespace 面。下面示例只允许受控 namespace 中、带例外标签的工作负载使用显式 Unconfined seccomp;生产规则还应加入镜像身份、ServiceAccount 与变更单约束。

rego

package kubernetes.admission  deny[msg] {   input.request.kind.kind == \"Pod\"   c := input.request.object.spec.containers[_]   not c.securityContext.seccompProfile.type   msg := sprintf(\"container %q must declare a seccomp profile\", [c.name]) }  deny[msg] {   input.request.kind.kind == \"Pod\"   c := input.request.object.spec.containers[_]   c.securityContext.seccompProfile.type == \"Unconfined\"   input.request.object.metadata.labels[\"security.example.com/seccomp-exception\"] != \"approved\"   msg := sprintf(\"container %q requests unapproved seccomp Unconfined\", [c.name]) }

5、利用工程的意义:逐层缓解都没有修复对象生命周期

公开课件描述了 KASLR、随机 kmalloc cache、RETHUNK、SMEP/SMAP、AppArmor 等缓解措施,以及研究者如何分别处理这些障碍。本文不展开可复用的地址计算、堆喷布局和调用链参数,但防守方必须理解一个事实:这些机制提高了利用成本,没有把错误引用关系变回正确关系。

以 CONFIG_RANDOM_KMALLOC_CACHES 为例,它按分配调用点映射随机子缓存,能破坏很多“从另一个调用点喷同尺寸对象”的传统堆布局。不过映射是按 callsite 稳定的;如果研究者能找到经过同一分配路径的对象,仍有机会落入相同子缓存。

RETHUNK 则把编译器生成的 ret 替换为返回跳板,主要约束经典的 return-oriented programming。课件转而利用内核已有的前向间接调用路径组织 call-oriented programming。这再次说明,控制流缓解的安全结论必须写成“约束了哪些边”,而不是笼统地写成“阻止代码执行”。

课件对各层缓解的总结很完整,但从防守工程角度还要补一列:这些缓解能否切断入口、能否阻止对象释放、能否阻止控制流接管,以及失效后是否有告警。否则一张“已启用缓解”清单很容易变成错误的安全证明。

6、容器逃逸不是“容器毫无安全性”,而是边界选错了

namespace、cgroup、capability、LSM 与 seccomp 能显著缩小进程权限和攻击面,但普通 OCI 容器仍与节点共享内核。只要某条路径允许容器内进程到达有漏洞的内核子系统,内核提权就可能跨过 namespace 隔离。

课件展示的后续目标包括进入宿主 mount namespace、访问节点文件与 kubelet 材料。真正需要被纳入风险模型的不是“攻击者得到容器内 uid 0”,而是以下资产是否与发生内核失陷的节点同生共死:

  • 同节点其他 Pod 的 Secret、服务账号令牌与应用数据;
  • kubelet 客户端证书、bootstrap 配置和云实例身份;
  • 宿主机容器运行时 socket、镜像缓存和审计配置;
  • 节点可访问的控制面、元数据服务与东西向网段。

如果业务确实执行不可信租户代码,边界应上移到独立内核:gVisor 通过用户态内核减少直接触达宿主 syscall 的范围;Kata Containers 等 microVM 方案把工作负载放进独立 guest kernel。它们仍需更新与隔离设计,但故障域不再等同于宿主共享内核。选择哪一种,要结合 syscall 兼容性、I/O 性能、启动延迟和租户风险,而不是一句“全部改 microVM”。

7、补丁核查必须识别 kernel flavor,不能只比版本字符串

截至 2026 年 8 月 10 日,Canonical 的 CVE 页面显示:Ubuntu 24.04 linux 已在 6.8.0-107.107 修复,linux-azure 为 6.8.0-1052.58,linux-gcp 为 6.8.0-1053.56,linux-gke 为 6.8.0-1049.54。同一发行版的不同 flavor 使用不同 ABI 和包版本;此外该页面仍列出少数 flavor 为 Vulnerable 或 work in progress。运维脚本不能把“数字看起来更大”当作修复证据。

下面的采集脚本只生成事实清单,不擅自判断所有衍生内核是否安全。判定基线应来自发行版公告或云厂商节点镜像公告,并在每次同步时记录来源时间。

bash

#!/usr/bin/env bashset -euo pipefail  printf'host=%s\
'\"$(hostname)\"printf'kernel_release=%s\
'\"$(uname -r)\"printf'kernel_version=%s\
'\"$(uname -v)\"printf'os_release=%s\
'\"$(. /etc/os-release; printf '%s %s' \"$ID\"\"$VERSION_ID\")\"  dpkg-query -W \\   -f='package=${binary:Package}\\tversion=${Version}\\tstatus=${db:Status-Abbrev}\
' \\   'linux-image-*' 2>/dev/null | awk '$0 ~ /ii $/' || true  sysctl kernel.unprivileged_userns_clone 2>/dev/null || true sysctl kernel.apparmor_restrict_unprivileged_userns 2>/dev/null || true sysctl kernel.apparmor_restrict_unprivileged_unconfined 2>/dev/null || true

集群侧至少要同时导出节点镜像、kernel、运行时与可调度工作负载:

bash

kubectl get nodes -o json | jq -r '   .items[] |   [ .metadata.name,     .status.nodeInfo.kernelVersion,     .status.nodeInfo.osImage,     .status.nodeInfo.containerRuntimeVersion,     (.metadata.labels[\"kubernetes.azure.com/node-image-version\"] // \"-\"),     (.metadata.labels[\"cloud.google.com/gke-nodepool\"] // \"-\")   ] | @tsv'

发布判定建议采用精确映射,而不是自行解析任意版本:

yaml

advisory:CVE-2026-23111checked_at:\"2026-08-10T00:00:00Z\"source:\"https://ubuntu.com/security/CVE-2026-23111\"minimum_fixed:ubuntu-24.04/linux:\"6.8.0-107.107\"ubuntu-24.04/linux-azure:\"6.8.0-1052.58\"ubuntu-24.04/linux-gcp:\"6.8.0-1053.56\"ubuntu-24.04/linux-gke:\"6.8.0-1049.54\"unknown_flavor_policy:block-and-reviewreboot_required:true

注意:软件包已安装不等于正在运行的内核已切换。升级后必须滚动重启或重建节点,再以 uname -r 和节点镜像版本回证。

8、SeccompDefault、Pod Security 与 AppArmor 应该怎样落地

课件建议启用 SeccompDefault、Restricted Pod Security,并收紧 Ubuntu AppArmor 的非特权 unconfined 行为。方向正确,但“启用 SeccompDefault 就杀掉所有 userns-based exploits”过于绝对。

Kubernetes 文档明确说明 RuntimeDefault 由容器运行时定义;不同运行时、版本和平台的默认 syscall 列表可能不同。因此,安全团队应把预期写成测试,而不是配置截图:

yaml

apiVersion:v1kind:Podmetadata:name:userns-negative-testnamespace:security-verificationspec:restartPolicy:NeverautomountServiceAccountToken:falsesecurityContext:seccompProfile:type:RuntimeDefaultcontainers:-name:probeimage:registry.example.com/security/userns-probe@sha256:REPLACE_MEargs: [\"--assert-userns-denied\", \"--assert-netlink-nft-denied\"]       securityContext:allowPrivilegeEscalation:falserunAsNonRoot:truerunAsUser:65532capabilities:drop: [\"ALL\"]         readOnlyRootFilesystem:true

探针应只验证系统调用和 Netlink 访问是否被拒绝,不创建真实 nftables 对象,更不触发漏洞。节点池升级、containerd 更新或 profile 变更后自动重跑。对于不能阻断 user namespace 的兼容性场景,至少保证修复内核已运行,并把高风险租户放入独立内核沙箱。

Pod Security restricted 能统一约束 privileged、host namespace、capabilities、seccomp 等常见风险项,但它不是内核补丁,也不会自动隔离共享内核。AppArmor sysctl 同样是纵深措施:变更前应盘点依赖非特权 user namespace 的浏览器沙箱、构建工具与桌面应用,先在专用节点池灰度。

9、检测重点不是猜 exploit,而是发现入口与失败事务异常

公开利用链细节可能变体很多,生产检测不应绑定某个进程名或固定次数。更可操作的三层信号是:

第一层看暴露面:哪些节点允许非特权 user namespace,哪些 Pod 使用 Unconfined seccomp,哪些节点仍运行受影响 flavor。第二层看行为:非网络管理工作负载是否创建 user/network namespace,是否异常高频访问 NETLINK_NETFILTER。第三层看结果:kernel warning、refcount 异常、nf\_tables UAF、节点突然重启、容器进入宿主 namespace 等。

Falco 风格规则可以先抓明显偏离基线的 namespace 行为。字段支持情况随版本与驱动而变,上线前需用本环境的 falco --list 校验:

yaml

-rule:UnexpectedUserNamespaceCreationInWorkloaddesc:非构建类容器尝试创建usernamespacecondition:>     container and evt.type in (unshare, clone, clone3) and     evt.dir = < and     not proc.name in (buildkitd, rootlesskit) and     not k8s.ns.name in (ci-builders, sandbox-lab) output:>     user namespace related syscall in workload     (proc=%proc.name cmd=%proc.cmdline container=%container.id pod=%k8s.pod.name ns=%k8s.ns.name) priority:WARNINGtags: [container, kernel, userns]

内核日志则要进入节点级采集,而不是只收容器 stdout:

yaml

sources:-journald:units: [kernel]       matches:-\"general protection fault\"-\"use-after-free\"-\"refcount_t:\"-\"nf_tables\"-\"KASAN:\"pipeline:enrich: [node_name, kernel_release, node_image, cluster, cloud_provider]   route:critical_when:-contains_any: [\"use-after-free\", \"KASAN:\"]       -all_of: [\"nf_tables\", \"general protection fault\"] response:-cordon_node-snapshot_volatile_telemetry-preserve_cloud_audit_logs-replace_node_from_known_good_image

不要在发现内核内存破坏后尝试“清理并继续运行”。节点完整性已经无法证明,安全动作应是隔离、保全证据、轮换节点可接触的凭据,然后从可信镜像重建。

10、把一个 ! 变成可执行的内核安全门禁

课件最后用“一行 diff 泄露完整研究路径”解释补丁部署窗口的危险。对安全工程团队而言,更重要的是把同类错误提前拦在代码和交付链里。

第一道门是代码结构:避免在关键状态判断上叠加否定,显式命名 is_active;activate/deactivate 不要只靠复制的循环骨架表达对称性。第二道门是模型测试:每个 prepare/commit/abort 序列都要验证引用计数、列表可达性和状态位守恒,并对重复 abort 做 property-based 测试。第三道门是内核动态检测:在测试内核上启用 KASAN、KFENCE、KCSAN 与 refcount 检查,使用 syzkaller 一类状态化模糊测试覆盖失败事务,而不是只 fuzz 单条合法消息。

一个适合 CI 的回滚属性可以写成:

rust

proptest! {     #[test]fnaborted_transaction_restores_observable_state(         ops inarb_reversible_operation_sequence()     ) {         letmut store = ModelStore::new();         letbefore = store.snapshot();          lettx = store.prepare(&ops)?;         store.abort(tx)?;          prop_assert_eq!(store.snapshot(), before);         prop_assert!(store.references_are_balanced());         prop_assert!(store.no_dangling_edges());     } }

第四道门是资产交付:以发行版和云厂商公告维护 flavor-aware 修复矩阵;节点升级后重启回证;例外节点设置到期时间。第五道门才是运行时缓解:默认 seccomp、Restricted Pod Security、LSM、最小 capability 与独立内核沙箱共同缩小爆炸半径。

CVE-2026-23111 的真正警示不是“一字符可以攻破一切”这种口号,而是三个具体工程事实:失败路径也是安全边界;引用计数必须用状态不变量验证;共享内核场景下,Pod 权限低不等于内核攻击面不可达。补丁是当前漏洞的终点,这三条才是下一类漏洞的起点。


资料来源

  • Black Hat 官方 Session 页面
  • Ubuntu:CVE-2026-23111
  • Kubernetes:Restrict a Container's Syscalls with seccomp
  • Kubernetes:Linux kernel security constraints for Pods and containers

原始会议材料(仓库内)

  • 演讲课件 PDF

开源资料与原始议题 PDF

本文对应的 Markdown 原稿、Black Hat 原始议题 PDF 与配图已整理到 GitHub,可按文章编号查找和下载。

https://github.com/cybermaxluo/black-hat-usa-2026-talks

也可以点击文末“阅读原文”进入仓库。欢迎 Star、提交 Issue 或参与勘误。


BlackHatUSA2026:Linux容器错误取反" 网络安全文章

BlackHatUSA2026:Linux容器错误取反"

本文解析BlackHatUSA2026议题CVE-2026-23111:Linuxnf\\_tables中nft\\_map\\_catchall\\_activate一处布尔取反错误破坏事务回滚一致性,重复失败事务可确定性耗尽引用计数引发UAF,在启用usernamespace与nftables环境普通用户可提权并逃逸共享内核的Kubernetes节点;各层缓解仅提高成本并未修复对象生命周期。建议按kernelflavor精确核查补丁版本并滚动重启节点,启用SeccompDefault与
Android恶意Shell脚本检测应用工具" 网络安全文章

Android恶意Shell脚本检测应用工具"

ShellGuard是一款Android本地恶意Shell脚本检测工具,通过C++/JNI混合引擎执行规则与特征匹配,覆盖反向Shell、命令执行、数据外传等恶意行为,并基于严重级别计算0-100风险评分。应用在本地处理所有扫描与历史记录,不上传数据至外部服务。用户可从GitHubReleases下载APK安装,支持Android8.0及以上版本。
青藤无相AI正式通过国家网信办生成式人工智能服务备案" 网络安全文章

青藤无相AI正式通过国家网信办生成式人工智能服务备案"

青藤云安全旗下高阶安全智能体无相AI正式通过国家网信办生成式人工智能服务备案,获得官方权威认可。该产品为L4级安全智能体,具备AI告警降噪、攻击链路还原、分钟级溯源等核心能力,覆盖实战对抗、日常运营等全业务场景,旨在以AI技术提升安全防御效率,为关键行业提供智能化解决方案。
奇安信获评NVDB多个安全漏洞专业库年度技术支撑单位" 网络安全文章

奇安信获评NVDB多个安全漏洞专业库年度技术支撑单位"

奇安信获评工信部NVDB平台2026年度五大安全漏洞专业库技术支撑单位,包括通用网络产品、工控、信创政务、车联网、人工智能产品,其中通用网络产品获四星级最高等级,人工智能产品获二星级当期最高。依托补天平台、巽丰工控实验室、代码安全实验室等团队,持续漏洞挖掘与报送,夯实国家漏洞治理体系。
评论:0   参与:  0