Mercurial > hg > nginx
changeset 9240:f3df785649ae
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.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sat, 30 Mar 2024 05:09:35 +0300 |
parents | b2e16e8639c8 |
children | 07ca679842de |
files | src/http/ngx_http.h src/http/ngx_http_parse.c src/http/ngx_http_request_body.c |
diffstat | 3 files changed, 35 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/http/ngx_http.h Sat Mar 30 05:09:12 2024 +0300 +++ b/src/http/ngx_http.h Sat Mar 30 05:09:35 2024 +0300 @@ -65,6 +65,7 @@ ngx_uint_t state; off_t size; off_t length; + off_t skipped; };
--- a/src/http/ngx_http_parse.c Sat Mar 30 05:09:12 2024 +0300 +++ b/src/http/ngx_http_parse.c Sat Mar 30 05:09:35 2024 +0300 @@ -2257,6 +2257,9 @@ break; case LF: state = sw_chunk_data; + break; + default: + ctx->skipped++; } break; @@ -2298,6 +2301,9 @@ break; case LF: state = sw_trailer; + break; + default: + ctx->skipped++; } break; @@ -2333,6 +2339,9 @@ break; case LF: state = sw_trailer; + break; + default: + ctx->skipped++; } break;
--- a/src/http/ngx_http_request_body.c Sat Mar 30 05:09:12 2024 +0300 +++ b/src/http/ngx_http_request_body.c Sat Mar 30 05:09:35 2024 +0300 @@ -1141,6 +1141,17 @@ 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 @@ 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);