HTTP/2 PUSH_PROMISE DoS
Medium
C
curl
Submitted None
Actions:
Reported by
w0x42
Vulnerability Details
Technical details and impact analysis
## Summary:
In `discard_newhandle` the condition in the `if` statement is always `false` for http transfer due to a negation.
As a result `http2_data_done` will never be called.
```
static void discard_newhandle(struct Curl_cfilter *cf,
struct Curl_easy *newhandle)
{
if(!newhandle->req.p.http) {
http2_data_done(cf, newhandle, TRUE);
newhandle->req.p.http = NULL;
}
(void)Curl_close(&newhandle);
}
```
`discard_newhandle` is supposed to close stream and free resources allocated in `http2_data_setup`
as well as close `Curl_easy` handle when some error occurs in `push_promise`.
For example if `PUSH_PROMISE` frame has invailid `:scheme` pseudo header `set_transfer_url` in `push_promise` will return an error.
```
rv = set_transfer_url(newhandle, &heads);
if(rv) {
discard_newhandle(cf, newhandle);
rv = CURL_PUSH_DENY;
goto fail;
}
```
An attacker could send specially crafted `PUSH_PROMISE` frames to trigger the error.
This would result in a memory leak for every malformed frame received, consequently using all available memory.
## Steps To Reproduce:
1. compile `nghttp2` with {F3099706} applied
1. compile {F3099707}
1. run `nghttpd -p/=/foo.bar --no-tls 8181`
1. run `valgrind --leak-check=full ./http2_push_headers`
for each `-p` option `nghttpd` will send 200 `PUSH_PROMISE` frames with invalid `:scheme` header
## Supporting Material/References:
`valgrind --leak-check=full ./http2_push_headers` output:
```
==5247==
==5247== HEAP SUMMARY:
==5247== in use at exit: 162,946 bytes in 873 blocks
==5247== total heap usage: 7,170 allocs, 6,297 frees, 1,696,049 bytes allocated
==5247==
==5247== 70,400 bytes in 200 blocks are definitely lost in loss record 6 of 7
==5247== at 0x48485EF: calloc (vg_replace_malloc.c:1340)
==5247== by 0x48ADC29: http2_data_setup (http2.c:249)
==5247== by 0x48AF154: h2_duphandle (http2.c:789)
==5247== by 0x48AF420: push_promise (http2.c:877)
==5247== by 0x48AFCF6: on_stream_frame (http2.c:1065)
==5247== by 0x48B08C7: on_frame_recv (http2.c:1265)
==5247== by 0x4C36AE3: nghttp2_session_mem_recv (in /usr/lib64/libnghttp2.so.14.26.0)
==5247== by 0x48AE851: h2_process_pending_input (http2.c:551)
==5247== by 0x48B294F: h2_progress_ingress (http2.c:1930)
==5247== by 0x48B2B54: cf_h2_recv (http2.c:1969)
==5247== by 0x4877F03: Curl_conn_recv (cfilters.c:183)
==5247== by 0x48DB1B3: Curl_read (sendf.c:813)
==5247==
==5247== LEAK SUMMARY:
==5247== definitely lost: 70,400 bytes in 200 blocks
==5247== indirectly lost: 0 bytes in 0 blocks
==5247== possibly lost: 0 bytes in 0 blocks
==5247== still reachable: 92,546 bytes in 673 blocks
==5247== suppressed: 0 bytes in 0 blocks
==5247== Reachable blocks (those to which a pointer was found) are not shown.
==5247== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==5247==
==5247== For lists of detected and suppressed errors, rerun with: -s
==5247== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
```
## Impact
denial of service
Report Details
Additional information and metadata
State
Closed
Substate
Informative
Submitted
Weakness
Uncontrolled Resource Consumption