# HG changeset patch # User Maxim Dounin <mdou...@mdounin.ru> # Date 1710526256 -10800 # Fri Mar 15 21:10:56 2024 +0300 # Node ID ece1df3184a22241682cb5ee8402dbb79015b204 # Parent 9f3e833ac0e10401d2da60953723d160c1bf4b5e Request body: limited chunk extensions and trailer headers.
Previously, arbitrary amounts of chunk extensions and trailer headers were accepted and skipped. Despite being under limit_conn / limit_req limits (if configured), this can be a DoS vector, so it is now limited by the client_max_body_size limit. Reported by Bartek Nowotarski. diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -65,6 +65,7 @@ struct ngx_http_chunked_s { ngx_uint_t state; off_t size; off_t length; + off_t skipped; }; diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -2257,6 +2257,9 @@ ngx_http_parse_chunked(ngx_http_request_ break; case LF: state = sw_chunk_data; + break; + default: + ctx->skipped++; } break; @@ -2298,6 +2301,9 @@ ngx_http_parse_chunked(ngx_http_request_ break; case LF: state = sw_trailer; + break; + default: + ctx->skipped++; } break; @@ -2333,6 +2339,9 @@ ngx_http_parse_chunked(ngx_http_request_ break; case LF: state = sw_trailer; + break; + default: + ctx->skipped++; } break; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -1141,6 +1141,17 @@ ngx_http_request_body_chunked_filter(ngx clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (clcf->client_max_body_size + && clcf->client_max_body_size < rb->chunked->skipped) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client sent too many chunk extensions"); + + r->lingering_close = 1; + + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + } + + if (clcf->client_max_body_size && clcf->client_max_body_size - r->headers_in.content_length_n < rb->chunked->size) { @@ -1241,6 +1252,20 @@ ngx_http_request_body_chunked_filter(ngx if (rc == NGX_AGAIN) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->client_max_body_size + && clcf->client_max_body_size < rb->chunked->skipped) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client sent too many chunk extensions " + "or trailer headers"); + + r->lingering_close = 1; + + return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; + } + /* set rb->rest, amount of data we want to see next time */ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); -- nginx-devel mailing list nginx-devel@freenginx.org https://freenginx.org/mailman/listinfo/nginx-devel