Merge of r4530, r4531: null character fixes.

*) Fixed incorrect ngx_cpystrn() usage in ngx_http_*_process_header().

   This resulted in a disclosure of previously freed memory if upstream
   server returned specially crafted response, potentially exposing
   sensitive information.

   Reported by Matthew Daley.

*) Headers with null character are now rejected.

   Headers with NUL character aren't allowed by HTTP standard and may cause
   various security problems.  They are now unconditionally rejected.
This commit is contained in:
Maxim Dounin 2012-03-15 11:41:43 +00:00
parent d5efcac176
commit 7b781638e8
5 changed files with 30 additions and 10 deletions

View File

@ -1446,10 +1446,10 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
h->lowcase_key = h->key.data + h->key.len + 1
+ h->value.len + 1;
ngx_cpystrn(h->key.data, r->header_name_start,
h->key.len + 1);
ngx_cpystrn(h->value.data, r->header_start,
h->value.len + 1);
ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
h->key.data[h->key.len] = '\0';
ngx_memcpy(h->value.data, r->header_start, h->value.len);
h->value.data[h->value.len] = '\0';
}
h->hash = r->header_hash;

View File

@ -1278,8 +1278,10 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
h->value.data = h->key.data + h->key.len + 1;
h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
h->key.data[h->key.len] = '\0';
ngx_memcpy(h->value.data, r->header_start, h->value.len);
h->value.data[h->value.len] = '\0';
if (h->key.len == r->lowcase_index) {
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);

View File

@ -894,8 +894,10 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
h->value.data = h->key.data + h->key.len + 1;
h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
h->key.data[h->key.len] = '\0';
ngx_memcpy(h->value.data, r->header_start, h->value.len);
h->value.data[h->value.len] = '\0';
if (h->key.len == r->lowcase_index) {
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);

View File

@ -947,8 +947,10 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
h->value.data = h->key.data + h->key.len + 1;
h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
h->key.data[h->key.len] = '\0';
ngx_memcpy(h->value.data, r->header_start, h->value.len);
h->value.data[h->value.len] = '\0';
if (h->key.len == r->lowcase_index) {
ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);

View File

@ -814,6 +814,10 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
break;
}
if (ch == '\0') {
return NGX_HTTP_PARSE_INVALID_HEADER;
}
r->invalid_header = 1;
break;
@ -876,6 +880,10 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
break;
}
if (ch == '\0') {
return NGX_HTTP_PARSE_INVALID_HEADER;
}
r->invalid_header = 1;
break;
@ -894,6 +902,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
r->header_start = p;
r->header_end = p;
goto done;
case '\0':
return NGX_HTTP_PARSE_INVALID_HEADER;
default:
r->header_start = p;
state = sw_value;
@ -915,6 +925,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
case LF:
r->header_end = p;
goto done;
case '\0':
return NGX_HTTP_PARSE_INVALID_HEADER;
}
break;
@ -928,6 +940,8 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
break;
case LF:
goto done;
case '\0':
return NGX_HTTP_PARSE_INVALID_HEADER;
default:
state = sw_value;
break;