BTC
ETH
SOL
BNB
GOLD
XRP
DOGE
ADA
Back to home
Security

[MEDIUM] Security Advisory: free5GC UDR: Fail-open handling in PolicyDataSubsToNotifyPost allows unintended subscription creation (github.com/free5gc/udr)

free5GC's UDR service contains a fail-open flaw in its POST handler for /nudr-dr/v2/policy-data/subs-to-notify.

free5GC’s UDR service contains a fail-open flaw in its POST handler for /nudr-dr/v2/policy-data/subs-to-notify. This endpoint creates notification subscriptions for policy data changes. When it fails to read or deserialize the request body, the code sends an error response but continues processing anyway. Attackers could exploit this to inject invalid or unintended subscriptions into the system.

free5GC is an open-source Go implementation of 5G core network functions, hosted on GitHub with over 1,500 stars and active use in research labs, universities, and some early commercial 5G pilots. Its UDR—Unified Data Repository—stores subscriber and policy data, feeding into the Policy Control Function (PCF) for decisions on QoS, charging, and network slicing. This bug sits in NFs/udr/internal/sbi/api_datarepository.go, around line 93 in the HandlePolicyDataSubsToNotifyPost function.

Technical Breakdown

The handler follows this broken sequence:

  1. Calls c.GetRawData() to fetch the raw HTTP body.
  2. On failure, logs an error, sends HTTP 500, but does not return.
  3. Proceeds to openapi.Deserialize(policyDataSubscription, reqBody, "application/json").
  4. On deserialization error, sends HTTP 400, but again skips return.
  5. Calls s.Processor().PolicyDataSubsToNotifyPostProcedure(c, policyDataSubscription) regardless.

This leaves the processor with a potentially uninitialized or garbage PolicyDataSubscription object. Other handlers in the same file use proper early returns, highlighting sloppy coding here. The 3GPP spec (TS 29.519) demands strict input validation before subscription creation, but free5GC ignores it post-error.

Static analysis confirms the path; runtime PoC for actual invalid subscription creation remains unproven, depending on the processor’s tolerance for bad data. In tests, you’d craft a malformed JSON body—say, truncated or non-JSON—to trigger the fail-open.

Security Impact and Real-World Risks

This isn’t a remote code execution dream, but it’s a robustness hole in a write API. Policy subscriptions notify external NFs (like PCF) of changes in subscriber policy data, such as data limits or priority levels. Invalid subs could flood notifications, cause storage bloat in UDR’s MongoDB backend, or create ghost subscriptions that misdirect policy enforcement.

Why this matters: 5G cores process billions of sessions daily. free5GC sees deployments in non-carrier setups—private 5G for factories, campuses—and even some telcos testing O-RAN. An attacker with API access (often exposed via SBI interfaces on non-prod ports) could disrupt service. Imagine bogus subs triggering endless PCF callbacks, spiking CPU and delaying real traffic. In worst cases, if the processor skips validation, it stores junk, leading to inconsistent state across the core.

Broaden the lens: Open-source 5G stacks like free5GC cut costs versus Ericsson or Nokia gear (which run $millions per site), but inherit dev bugs. Similar fail-open issues plague other free5GC components—AMF auth bypasses in 2022, NRF DoS last year. OSS-Fuzz hasn’t fully audited this repo yet. Telcos deploying it save 80-90% upfront but risk outages if unpatched. No CVSS yet, but it’d score 5-7ish: medium AV:N/AC:L, low impact.

Exploitation needs network access, likely internal or via misconfigs. Still, in edge 5G where UDR faces the wild, it’s a vector. Pair with SBI spoofing (common in 5G pentests), and you amplify.

Patch and Mitigation

Fix is straightforward: Add return after each error response. Here’s the minimal diff:

reqBody, err := c.GetRawData()
if err != nil {
    logger.DataRepoLog.Errorf("Get RawData failed: %v", err)
    c.JSON(http.StatusInternalServerError, gin.H{"cause": "INTERNAL_ERROR"})
    return  // Add this
}
policyDataSubscription := PolicyDataSubscription{}
if err := openapi.Deserialize(&policyDataSubscription, reqBody, "application/json"); err != nil {
    problem, ok := err.(*openapi.GenericOpenAPIError)
    if !ok {
        logger.DataRepoLog.Errorf("Deserialize failed: %v", err)
        c.JSON(http.StatusBadRequest, gin.H{"cause": "INVALID_INPUT"})
        return  // Add this too
    }
    c.JSON(int(problem.Status), problem.Value)
    return
}

Upstream PR pending; check free5GC/udr. Interim: Firewall the endpoint or run behind auth proxy. Audit similar handlers—UDR has 20+ SBI paths. Run go vet and fuzz with go test -race.

Bottom line: Patch now if running free5GC. This exposes how rushed OSS 5G code trades security for speed. Vet your stack—5G’s complexity (hundreds of TS docs) breeds these bugs. Watch for advisories; free5GC’s velocity means fixes land fast, but so do vulns.

April 22, 2026 · 4 min · 5 views · Source: GitHub Security

Related