mirror of
https://github.com/nginx/nginx.git
synced 2026-05-28 04:12:47 -04:00
Proxy: fix large body with proxy_set_body and HTTP/2
Previously, if proxy_set_body was used with HTTP/2, and body size exceeded 16M, then an overflow happened in the 24-bit DATA frame size, which resulted in sending unframed bytes, potentially allowing for an injection. Also, DATA frame size could exceed NGX_HTTP_V2_DEFAULT_FRAME_SIZE (16K) and available send window. Reported by Mufeed VH of Winfunc Research.
This commit is contained in:
parent
524977e7c5
commit
a0e742944d
1 changed files with 33 additions and 35 deletions
|
|
@ -458,9 +458,6 @@ ngx_http_proxy_v2_create_request(ngx_http_request_t *r)
|
|||
|
||||
ctx->ctx.internal_body_length = body_len;
|
||||
|
||||
len += sizeof(ngx_http_proxy_v2_frame_t);
|
||||
len += body_len;
|
||||
|
||||
} else if (r->headers_in.chunked && r->reading_body) {
|
||||
ctx->ctx.internal_body_length = -1;
|
||||
|
||||
|
|
@ -834,34 +831,6 @@ ngx_http_proxy_v2_create_request(ngx_http_request_t *r)
|
|||
|
||||
f->flags |= NGX_HTTP_V2_END_HEADERS_FLAG;
|
||||
|
||||
if (plcf->body_values) {
|
||||
f = (ngx_http_proxy_v2_frame_t *) b->last;
|
||||
b->last += sizeof(ngx_http_proxy_v2_frame_t);
|
||||
|
||||
f->length_0 = (u_char) ((body_len >> 16) & 0xff);
|
||||
f->length_1 = (u_char) ((body_len >> 8) & 0xff);
|
||||
f->length_2 = (u_char) (body_len & 0xff);
|
||||
f->type = NGX_HTTP_V2_DATA_FRAME;
|
||||
f->flags = NGX_HTTP_V2_END_STREAM_FLAG;
|
||||
f->stream_id_0 = 0;
|
||||
f->stream_id_1 = 0;
|
||||
f->stream_id_2 = 0;
|
||||
f->stream_id_3 = 1;
|
||||
|
||||
e.ip = plcf->body_values->elts;
|
||||
e.pos = b->last;
|
||||
e.request = r;
|
||||
e.flushed = 1;
|
||||
e.skip = 0;
|
||||
|
||||
while (*(uintptr_t *) e.ip) {
|
||||
code = *(ngx_http_script_code_pt *) e.ip;
|
||||
code((ngx_http_script_engine_t *) &e);
|
||||
}
|
||||
|
||||
b->last = e.pos;
|
||||
}
|
||||
|
||||
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http proxy header: %*xs%s, len: %uz",
|
||||
(size_t) ngx_min(b->last - b->pos, 256), b->pos,
|
||||
|
|
@ -903,13 +872,42 @@ ngx_http_proxy_v2_create_request(ngx_http_request_t *r)
|
|||
|
||||
b->last_buf = 1;
|
||||
|
||||
} else if (body_len) {
|
||||
|
||||
u->request_bufs = cl;
|
||||
|
||||
b = ngx_create_temp_buf(r->pool, body_len);
|
||||
if (b == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cl->next = ngx_alloc_chain_link(r->pool);
|
||||
if (cl->next == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cl = cl->next;
|
||||
cl->buf = b;
|
||||
|
||||
e.ip = plcf->body_values->elts;
|
||||
e.pos = b->last;
|
||||
e.request = r;
|
||||
e.flushed = 1;
|
||||
e.skip = 0;
|
||||
|
||||
while (*(uintptr_t *) e.ip) {
|
||||
code = *(ngx_http_script_code_pt *) e.ip;
|
||||
code((ngx_http_script_engine_t *) &e);
|
||||
}
|
||||
|
||||
b->last = e.pos;
|
||||
b->last_buf = 1;
|
||||
|
||||
} else {
|
||||
u->request_bufs = cl;
|
||||
|
||||
if (plcf->body_values == NULL) {
|
||||
f = (ngx_http_proxy_v2_frame_t *) headers_frame;
|
||||
f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;
|
||||
}
|
||||
f = (ngx_http_proxy_v2_frame_t *) headers_frame;
|
||||
f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;
|
||||
|
||||
b->last_buf = 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue