mirror of
https://github.com/nginx/nginx.git
synced 2025-07-25 22:56:59 +08:00
HTTP: reject invalid header names
HTTP headers must be an RFC9110 token, so only a subset of characters are permitted. RFC9113 and RFC9114 require rejecting invalid header characters in HTTP/2 and HTTP/3 respectively, so reject them in HTTP/1.0 and HTTP/1.1 for consistency. This also requires removing the ignore hack for (presumably ancient) versions of IIS.
This commit is contained in:
parent
bccf2b1f3b
commit
2fbc33e2de
@ -811,6 +811,29 @@ done:
|
|||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_non_alnum_dash_header_char(u_char ch)
|
||||||
|
{
|
||||||
|
switch (ch) {
|
||||||
|
case '!':
|
||||||
|
case '#':
|
||||||
|
case '$':
|
||||||
|
case '%':
|
||||||
|
case '&':
|
||||||
|
case '\'':
|
||||||
|
case '*':
|
||||||
|
case '+':
|
||||||
|
case '.':
|
||||||
|
case '^':
|
||||||
|
case '_':
|
||||||
|
case '`':
|
||||||
|
case '|':
|
||||||
|
case '~':
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
||||||
@ -824,7 +847,6 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
sw_space_before_value,
|
sw_space_before_value,
|
||||||
sw_value,
|
sw_value,
|
||||||
sw_space_after_value,
|
sw_space_after_value,
|
||||||
sw_ignore_line,
|
|
||||||
sw_almost_done,
|
sw_almost_done,
|
||||||
sw_header_almost_done
|
sw_header_almost_done
|
||||||
} state;
|
} state;
|
||||||
@ -875,22 +897,14 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == '_') {
|
if (ch == '_' && allow_underscores) {
|
||||||
if (allow_underscores) {
|
hash = ngx_hash(0, ch);
|
||||||
hash = ngx_hash(0, ch);
|
r->lowcase_header[0] = ch;
|
||||||
r->lowcase_header[0] = ch;
|
i = 1;
|
||||||
i = 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
hash = 0;
|
|
||||||
i = 0;
|
|
||||||
r->invalid_header = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch <= 0x20 || ch == 0x7f || ch == ':') {
|
if (!ngx_http_non_alnum_dash_header_char(ch)) {
|
||||||
r->header_end = p;
|
r->header_end = p;
|
||||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
@ -949,17 +963,7 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IIS may send the duplicate "HTTP/1.1 ..." lines */
|
if (!ngx_http_non_alnum_dash_header_char(ch)) {
|
||||||
if (ch == '/'
|
|
||||||
&& r->upstream
|
|
||||||
&& p - r->header_name_start == 4
|
|
||||||
&& ngx_strncmp(r->header_name_start, "HTTP", 4) == 0)
|
|
||||||
{
|
|
||||||
state = sw_ignore_line;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ch <= 0x20 || ch == 0x7f) {
|
|
||||||
r->header_end = p;
|
r->header_end = p;
|
||||||
return NGX_HTTP_PARSE_INVALID_HEADER;
|
return NGX_HTTP_PARSE_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
@ -1034,17 +1038,6 @@ ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* ignore header line */
|
|
||||||
case sw_ignore_line:
|
|
||||||
switch (ch) {
|
|
||||||
case LF:
|
|
||||||
state = sw_start;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* end of header line */
|
/* end of header line */
|
||||||
case sw_almost_done:
|
case sw_almost_done:
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@ -1125,8 +1118,7 @@ ngx_http_v23_validate_header(ngx_http_request_t *r, ngx_str_t *name,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch <= 0x20 || ch == 0x7f || ch == ':'
|
if (!ngx_http_non_alnum_dash_header_char(ch))
|
||||||
|| (ch >= 'A' && ch <= 'Z'))
|
|
||||||
{
|
{
|
||||||
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
"client sent invalid header name");
|
"client sent invalid header name");
|
||||||
|
Loading…
Reference in New Issue
Block a user