mirror of
https://github.com/nginx/nginx.git
synced 2025-06-08 02:02:38 +08:00
Now if total size of all ranges is greater than source response size,
then nginx disables ranges and returns just the source response. This fix should not affect well-behaving applications but will defeat DoS attempts exploiting malicious byte ranges.
This commit is contained in:
parent
8b2bf08165
commit
c2c3e3105f
@ -146,7 +146,6 @@ static ngx_int_t
|
|||||||
ngx_http_range_header_filter(ngx_http_request_t *r)
|
ngx_http_range_header_filter(ngx_http_request_t *r)
|
||||||
{
|
{
|
||||||
time_t if_range;
|
time_t if_range;
|
||||||
ngx_int_t rc;
|
|
||||||
ngx_http_range_filter_ctx_t *ctx;
|
ngx_http_range_filter_ctx_t *ctx;
|
||||||
|
|
||||||
if (r->http_version < NGX_HTTP_VERSION_10
|
if (r->http_version < NGX_HTTP_VERSION_10
|
||||||
@ -192,10 +191,9 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ngx_http_range_parse(r, ctx);
|
switch (ngx_http_range_parse(r, ctx)) {
|
||||||
|
|
||||||
if (rc == NGX_OK) {
|
|
||||||
|
|
||||||
|
case NGX_OK:
|
||||||
ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
|
ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
|
||||||
|
|
||||||
r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
|
r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
|
||||||
@ -206,16 +204,17 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ngx_http_range_multipart_header(r, ctx);
|
return ngx_http_range_multipart_header(r, ctx);
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == NGX_HTTP_RANGE_NOT_SATISFIABLE) {
|
case NGX_HTTP_RANGE_NOT_SATISFIABLE:
|
||||||
return ngx_http_range_not_satisfiable(r);
|
return ngx_http_range_not_satisfiable(r);
|
||||||
|
|
||||||
|
case NGX_ERROR:
|
||||||
|
return NGX_ERROR;
|
||||||
|
|
||||||
|
default: /* NGX_DECLINED */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rc == NGX_ERROR */
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
next_filter:
|
next_filter:
|
||||||
|
|
||||||
r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
|
r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
|
||||||
@ -235,11 +234,12 @@ ngx_int_t
|
|||||||
ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx)
|
ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
u_char *p;
|
u_char *p;
|
||||||
off_t start, end;
|
off_t start, end, size;
|
||||||
ngx_uint_t suffix;
|
ngx_uint_t suffix;
|
||||||
ngx_http_range_t *range;
|
ngx_http_range_t *range;
|
||||||
|
|
||||||
p = r->headers_in.range->value.data + 6;
|
p = r->headers_in.range->value.data + 6;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
start = 0;
|
start = 0;
|
||||||
@ -277,9 +277,10 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx)
|
|||||||
|
|
||||||
range->start = start;
|
range->start = start;
|
||||||
range->end = r->headers_out.content_length_n;
|
range->end = r->headers_out.content_length_n;
|
||||||
|
size += range->end - start;
|
||||||
|
|
||||||
if (*p++ != ',') {
|
if (*p++ != ',') {
|
||||||
return NGX_OK;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@ -331,10 +332,18 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx)
|
|||||||
range->end = end + 1;
|
range->end = end + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size += range->end - start;
|
||||||
|
|
||||||
if (*p++ != ',') {
|
if (*p++ != ',') {
|
||||||
return NGX_OK;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size > r->headers_out.content_length_n) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user