Loading HuntDB...

CVE-2024-2398: HTTP/2 push headers memory-leak

Medium
C
curl
Submitted None
Reported by w0x42

Vulnerability Details

Technical details and impact analysis

Uncontrolled Resource Consumption
## Summary: For each incoming `PUSH_PROMISE` header a new `name:value` string is allocated and the pointer to that string is stored in the `stream->push_headers` array. ``` h = aprintf("%s:%s", name, value); if(h) stream->push_headers[stream->push_headers_used++] = h; ``` Libcurl will reject `PUSH_PROMISE` frames with too many headers. When the number of headers exceeds some threshold, `on_header` returns an error. However, libcurl forgets to free the `stream->push_headers` array elements before `stream->push_headers` is freed. A malicious server may continuously send `PUSH_PROMISE` frames with over 1000 headers, which would eventually consume all available memory. The same issue exists when `Curl_saferealloc` fails. ``` if(stream->push_headers_alloc > 1000) { /* this is beyond crazy many headers, bail out */ failf(data_s, "Too many PUSH_PROMISE headers"); Curl_safefree(stream->push_headers); return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } stream->push_headers_alloc *= 2; headp = Curl_saferealloc(stream->push_headers, stream->push_headers_alloc * sizeof(char *)); if(!headp) { stream->push_headers = NULL; return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } ``` ## Steps To Reproduce: 1. compile `nghttp2` with {F3099659} applied 1. compile {F3099658} 1. run `nghttpd -p/=/foo.bar --no-tls 8181` 1. run `valgrind --leak-check=full http2_push_promise` for each `-p` option `nghttpd` will send 200 `PUSH_PROMISE` frames, each with 1280 headers (not counting pseudo headers) ## Supporting Material/References: `valgrind --leak-check=full http2_push_promise` output: ``` ==13928== ==13928== HEAP SUMMARY: ==13928== in use at exit: 8,285,018 bytes in 256,674 blocks ==13928== total heap usage: 261,567 allocs, 4,893 frees, 12,766,009 bytes allocated ==13928== ==13928== 64 bytes in 2 blocks are possibly lost in loss record 2 of 10 ==13928== at 0x48436C4: malloc (vg_replace_malloc.c:392) ==13928== by 0x4889F45: dyn_nappend (dynbuf.c:107) ==13928== by 0x488A2C5: Curl_dyn_addn (dynbuf.c:170) ==13928== by 0x48C393E: alloc_addbyter (mprintf.c:1065) ==13928== by 0x48C2FF9: dprintf_formatf (mprintf.c:852) ==13928== by 0x48C39FF: curl_mvaprintf (mprintf.c:1095) ==13928== by 0x48C3AF0: curl_maprintf (mprintf.c:1110) ==13928== by 0x48B0F86: on_header (http2.c:1467) ==13928== by 0x4C310C1: nghttp2_session_mem_recv (in /usr/lib64/libnghttp2.so.14.25.1) ==13928== by 0x48AE62B: h2_process_pending_input (http2.c:552) ==13928== by 0x48B2570: h2_progress_ingress (http2.c:1914) ==13928== by 0x48B2775: cf_h2_recv (http2.c:1953) ==13928== ==13928== 8,191,872 bytes in 255,996 blocks are definitely lost in loss record 10 of 10 ==13928== at 0x48436C4: malloc (vg_replace_malloc.c:392) ==13928== by 0x4889F45: dyn_nappend (dynbuf.c:107) ==13928== by 0x488A2C5: Curl_dyn_addn (dynbuf.c:170) ==13928== by 0x48C393E: alloc_addbyter (mprintf.c:1065) ==13928== by 0x48C2FF9: dprintf_formatf (mprintf.c:852) ==13928== by 0x48C39FF: curl_mvaprintf (mprintf.c:1095) ==13928== by 0x48C3AF0: curl_maprintf (mprintf.c:1110) ==13928== by 0x48B0F86: on_header (http2.c:1467) ==13928== by 0x4C310C1: nghttp2_session_mem_recv (in /usr/lib64/libnghttp2.so.14.25.1) ==13928== by 0x48AE62B: h2_process_pending_input (http2.c:552) ==13928== by 0x48B2570: h2_progress_ingress (http2.c:1914) ==13928== by 0x48B2775: cf_h2_recv (http2.c:1953) ==13928== ==13928== LEAK SUMMARY: ==13928== definitely lost: 8,191,872 bytes in 255,996 blocks ==13928== indirectly lost: 0 bytes in 0 blocks ==13928== possibly lost: 64 bytes in 2 blocks ==13928== still reachable: 93,082 bytes in 676 blocks ==13928== suppressed: 0 bytes in 0 blocks ==13928== Reachable blocks (those to which a pointer was found) are not shown. ==13928== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==13928== ==13928== For lists of detected and suppressed errors, rerun with: -s ==13928== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ``` ## Impact denial of service

Report Details

Additional information and metadata

State

Closed

Substate

Resolved

Submitted

Weakness

Uncontrolled Resource Consumption