Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify we do not receive multiple content-length headers or a content-length and transfer-encoding: chunked header when using HTTP/1.1 #9865

Merged
merged 3 commits into from
Dec 13, 2019

Conversation

normanmaurer
Copy link
Member

@normanmaurer normanmaurer commented Dec 10, 2019

Motivation:

RFC7230 states that we should not accept multiple content-length headers and also should not accept a content-length header in combination with transfer-encoding: chunked

Modifications:

  • Check for multiple content-length headers and if found mark message as invalid
  • Check if we found a content-length header and also a transfer-encoding: chunked and if so mark the message as invalid
  • Add unit test

Result:

Fixes #9861

@normanmaurer
Copy link
Member Author

This is also what http_parser does:

https://github.com/nodejs/http-parser/blob/master/http_parser.c#L1430

@normanmaurer
Copy link
Member Author

@amizurov maybe you also want to review

@normanmaurer normanmaurer added this to the 4.1.44.Final milestone Dec 11, 2019
@normanmaurer normanmaurer changed the title Verify we do not receive multiple content-length headers when using H… Verify we do not receive multiple content-length headers or a content-length and transfer-encoding: chunked header when using HTTP/1.1 Dec 11, 2019
@normanmaurer normanmaurer force-pushed the headers_verify branch 2 times, most recently from 9f5f64d to fc8b1d5 Compare December 11, 2019 13:09
Copy link

@jayv jayv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, maybe add RFC test-case

…-length and transfer-encoding: chunked header when using HTTP/1.1

Motivation:

RFC7230 states that we should not accept multiple content-length headers and also should not accept a content-length header in combination with transfer-encoding: chunked

Modifications:

- Check for multiple content-length headers and if found mark message as invalid
- Check if we found a content-length header and also a transfer-encoding: chunked and if so mark the message as invalid
- Add unit test

Result:

Fixes #9861
@normanmaurer
Copy link
Member Author

@netty-bot test this please

@normanmaurer
Copy link
Member Author

@netty-bot test this please

@normanmaurer
Copy link
Member Author

@netty-bot test this please

Copy link
Member

@NiteshKant NiteshKant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM, few minor suggestions

@normanmaurer
Copy link
Member Author

@netty-bot test this please

@normanmaurer normanmaurer merged commit 8494b04 into 4.1 Dec 13, 2019
@normanmaurer normanmaurer deleted the headers_verify branch December 13, 2019 07:53
normanmaurer added a commit that referenced this pull request Dec 13, 2019
…-length and transfer-encoding: chunked header when using HTTP/1.1 (#9865)

Motivation:

RFC7230 states that we should not accept multiple content-length headers and also should not accept a content-length header in combination with transfer-encoding: chunked

Modifications:

- Check for multiple content-length headers and if found mark message as invalid
- Check if we found a content-length header and also a transfer-encoding: chunked and if so mark the message as invalid
- Add unit test

Result:

Fixes #9861
dalaro pushed a commit to dalaro/netty that referenced this pull request Mar 30, 2020
…-length and transfer-encoding: chunked header when using HTTP/1.1 (netty#9865)

Motivation:

RFC7230 states that we should not accept multiple content-length headers and also should not accept a content-length header in combination with transfer-encoding: chunked

Modifications:

- Check for multiple content-length headers and if found mark message as invalid
- Check if we found a content-length header and also a transfer-encoding: chunked and if so mark the message as invalid
- Add unit test

Result:

Fixes netty#9861

(cherry picked from commit 8494b04)
dalaro added a commit to dalaro/netty that referenced this pull request Apr 7, 2020
Compared against 4.1.25.6.dse, this tag cherry-picks upstream commits
that fixed bugs in HttpObjectDecoder/HttpRequestDecoder, plus two
intermediate refactoring commits that indirectly affect those bugfix
commits.

What follows is a list of PR links, issue links, CVE links, and hashes
associated with the cherry-picked commits.

Verify we do not receive multiple content-length headers or a content-length and transfer-encoding: chunked header when using HTTP/1.1 (netty#9865)
	https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7238
	netty#9861
	netty#9865

	8494b04

Detect missing colon when parsing http headers with no value (netty#9871)
	GHSA-cqqj-4p63-rrmm
	netty#9866
	netty#9871

	a7c18d4

Fix typos in javadocs (netty#9527)
	skipped

Correctly handle whitespaces in HTTP header names as defined by RFC7230#section-3.2.4 (netty#9585)
	https://nvd.nist.gov/vuln/detail/CVE-2019-16869
	netty#9571
	netty#9585

	39cafcb

Use `AppendableCharSequence.charAtUnsafe(int)` in `HttpObjectDecoder` (netty#9492)
	netty#9492

	85fcf4e

use checkPositive/checkPositiveOrZero (netty#8835)
	netty#8835

	4c64c98

HttpObjectDecoder ignores HTTP trailer header when empty line is rece… (netty#8799)
	netty#8736
	netty#8799

	91d3920
dalaro added a commit to dalaro/netty that referenced this pull request Apr 7, 2020
Compared against 4.1.34.2.dse, this tag cherry-picks upstream commits
that fixed bugs in HttpObjectDecoder/HttpRequestDecoder, plus two
intermediate refactoring commits that indirectly affect those bugfix
commits.

What follows is a list of PR links, issue links, CVE links, and hashes
associated with the cherry-picked commits.

Verify we do not receive multiple content-length headers or a content-length and transfer-encoding: chunked header when using HTTP/1.1 (netty#9865)
	https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7238
	netty#9861
	netty#9865

	8494b04

Detect missing colon when parsing http headers with no value (netty#9871)
	https://nvd.nist.gov/vuln/detail/CVE-2019-20444
	netty#9866
	netty#9871

	a7c18d4

Fix typos in javadocs (netty#9527)
	skipped

Correctly handle whitespaces in HTTP header names as defined by RFC7230#section-3.2.4 (netty#9585)
	https://nvd.nist.gov/vuln/detail/CVE-2019-16869
	netty#9571
	netty#9585

	39cafcb

Use `AppendableCharSequence.charAtUnsafe(int)` in `HttpObjectDecoder` (netty#9492)
	netty#9492

	85fcf4e
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request May 25, 2020
...and introduce HttpDecoderOption & HttpDecoderBuilder in doing so.

Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior. While it makes sense for Netty
to bias towards the safest option, Netty is used as a library for a
variety of different use cases, and there is usually no
one-size-fits-all for parsing behavior like this...

It seems like the ideal solution would be to default to the safest
behavior but to also make these types of decisions configurable. This is
further motivated by the fact that the HTTP RFCs are often vague or
ambiguous in many areas and we have seen other back-and-forth
conversations (e.g., netty#10003) based
on differing interpretations that would probably be most amicably
resolved by simply exposing better configuration.

Modifications

* Deprecate HttpRequestDecoder's telescoping constructors and introduce
AbstractHttpObjectDecoderBuilder and HttpRequestDecoderBuilder.
(The current HttpObjectDecoder implementations are only
minimally configurable, and any further configuration will not scale
well with the existing telescoping constructors.)
* Move default decoder values to the HttpObjectDecoder class and
reference them accordingly.
* Introduce HttpDecoderOption class. This option is similar in vein to
the ChannelOption class, where it is capable of exposing a wide
possibility of different configurations.
* Introduce the first decoder option:
MultipleContentLengthHeadersBehavior. This option sets the precedent of
using an interface for its implementation (as opposed to boolean/enum)
so that users can easily define their own implementations or even
"listen in" on implementations for logging purposes (without having to
override).
* Current available options are: ALWAYS_REJECT,
IF_DIFFERENT_REJECT_ELSE_DEDUPE, and IF_DIFFERENT_REJECT_ELSE_ALLOW (see
Javadoc for more).
* Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
 reports these as IllegalArgumentException.
* Extend HttpObjectDecoder to accept a map of options and use these
options to resolve multiple Content-Length scenarios.
* In doing so, also apply this logic to HTTP/1.0 (in addition to 1.1).
Even though the cited RFCs were for 1.1, it seems that the risks they
are trying to mitigate could still apply to messages in 1.0 that specify
a content length.
* Also include HTTP/1.0 in the existing
"handleTransferEncodingChunkedWithContentLength" logic for the same
reason (this logic could also probably be better served by an
HttpDecoderOption in the future).
* Include new unit tests to test all of the possible combinations of
MultipleContentLengthHeadersBehavior and multiple content lengths.

Result

This is a backwards-compatible change with no functional change to the
existing behavior. Users will now be able to customize the behavior for
handling multiple content lengths, and we will be able to more easily
add additional options in the future if needed.

To limit the scope of this commit, it does not attempt to introduce the
builder or decoder options to the other relevant classes
(HttpResponseDecoder, HttpClientCodec, HttpServerCodec), but we may wish
to follow-up with those changes.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request May 28, 2020
...and introduce HttpDecoderOption & HttpDecoderBuilder in doing so.

Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior. While it makes sense for Netty
to bias towards the safest option, Netty is used as a library for a
variety of different use cases, and there is usually no
one-size-fits-all for parsing behavior like this...

It seems like the ideal solution would be to default to the safest
behavior but to also make these types of decisions configurable. This is
further motivated by the fact that the HTTP RFCs are often vague or
ambiguous in many areas and we have seen other back-and-forth
conversations (e.g., netty#10003) based
on differing interpretations that would probably be most amicably
resolved by simply exposing better configuration.

Modifications

* Deprecate HttpRequestDecoder's telescoping constructors and introduce
AbstractHttpObjectDecoderBuilder and HttpRequestDecoderBuilder.
(The current HttpObjectDecoder implementations are only
minimally configurable, and any further configuration will not scale
well with the existing telescoping constructors.)
* Move default decoder values to the HttpObjectDecoder class and
reference them accordingly.
* Introduce HttpDecoderOption class. This option is similar in vein to
the ChannelOption class, where it is capable of exposing a wide
possibility of different configurations.
* Introduce the first decoder option:
MultipleContentLengthHeadersBehavior. This option sets the precedent of
using an interface for its implementation (as opposed to boolean/enum)
so that users can easily define their own implementations or even
"listen in" on implementations for logging purposes (without having to
override).
* Current available options are: ALWAYS_REJECT,
IF_DIFFERENT_REJECT_ELSE_DEDUPE, and IF_DIFFERENT_REJECT_ELSE_ALLOW (see
Javadoc for more).
* Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
 reports these as IllegalArgumentException.
* Extend HttpObjectDecoder to accept a map of options and use these
options to resolve multiple Content-Length scenarios.
* In doing so, also apply this logic to HTTP/1.0 (in addition to 1.1).
Even though the cited RFCs were for 1.1, it seems that the risks they
are trying to mitigate could still apply to messages in 1.0 that specify
a content length.
* Also include HTTP/1.0 in the existing
"handleTransferEncodingChunkedWithContentLength" logic for the same
reason (this logic could also probably be better served by an
HttpDecoderOption in the future).
* Include new unit tests to test all of the possible combinations of
MultipleContentLengthHeadersBehavior and multiple content lengths.

Result

This is a backwards-compatible change with no functional change to the
existing behavior. Users will now be able to customize the behavior for
handling multiple content lengths, and we will be able to more easily
add additional options in the future if needed.

To limit the scope of this commit, it does not attempt to introduce the
builder or decoder options to the other relevant classes
(HttpResponseDecoder, HttpClientCodec, HttpServerCodec), but we may wish
to follow-up with those changes.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request Jun 12, 2020
Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request Jun 12, 2020
Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request Jun 15, 2020
Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request Jun 24, 2020
Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request Jun 24, 2020
Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
Bennett-Lynch added a commit to Bennett-Lynch/netty that referenced this pull request Jun 25, 2020
Motivation

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
normanmaurer pushed a commit that referenced this pull request Jul 6, 2020
…10349)


Motivation:

Since #9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications:

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result:

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
normanmaurer pushed a commit that referenced this pull request Jul 6, 2020
…10349)

Motivation:

Since #9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications:

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result:

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
ihanyong pushed a commit to ihanyong/netty that referenced this pull request Jul 31, 2020
…-length and transfer-encoding: chunked header when using HTTP/1.1 (netty#9865)

Motivation:

RFC7230 states that we should not accept multiple content-length headers and also should not accept a content-length header in combination with transfer-encoding: chunked

Modifications:

- Check for multiple content-length headers and if found mark message as invalid
- Check if we found a content-length header and also a transfer-encoding: chunked and if so mark the message as invalid
- Add unit test

Result:

Fixes netty#9861
ihanyong pushed a commit to ihanyong/netty that referenced this pull request Jul 31, 2020
…etty#10349)

Motivation:

Since netty#9865 (Netty 4.1.44) the
default behavior of the HttpObjectDecoder has been to reject any HTTP
message that is found to have multiple Content-Length headers when
decoding. This behavior is well-justified as per the risks outlined in
netty#9861, however, we can see from the
cited RFC section that there are multiple possible options offered for
responding to this scenario:

> If a message is received that has multiple Content-Length header
> fields with field-values consisting of the same decimal value, or a
> single Content-Length header field with a field value containing a
> list of identical decimal values (e.g., "Content-Length: 42, 42"),
> indicating that duplicate Content-Length header fields have been
> generated or combined by an upstream message processor, then the
> recipient MUST either reject the message as invalid or replace the
> duplicated field-values with a single valid Content-Length field
> containing that decimal value prior to determining the message body
> length or forwarding the message.

https://tools.ietf.org/html/rfc7230#section-3.3.2

Netty opted for the first option (rejecting as invalid), which seems
like the safest, but the second option (replacing duplicate values with
a single value) is also valid behavior.

Modifications:

* Introduce "allowDuplicateContentLengths" parameter to
HttpObjectDecoder (defaulting to false).
* When set to true, will allow multiple Content-Length headers only if
they are all the same value. The duplicated field-values will be
replaced with a single valid Content-Length field.
* Add new parameterized test class for testing different variations of
multiple Content-Length headers.

Result:

This is a backwards-compatible change with no functional change to the
existing behavior.

Note that the existing logic would result in NumberFormatExceptions
for header values like "Content-Length: 42, 42". The new logic correctly
reports these as IllegalArgumentException with the proper error message.

Additionally note that this behavior is only applied to HTTP/1.1, but I
suspect that we may want to expand that to include HTTP/1.0 as well...
That behavior is not modified here to minimize the scope of this change.
suneet-s added a commit to suneet-s/netty that referenced this pull request Aug 19, 2020
suneet-s added a commit to implydata/netty that referenced this pull request Aug 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Non-proper handling of Content-Length and Transfer-Encoding: chunked headers
4 participants