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

HCM: protect against removal of critical response headers by a filter chain. #16745

Merged
merged 8 commits into from
Jun 2, 2021

Conversation

mathetake
Copy link
Member

@mathetake mathetake commented Jun 1, 2021

This is the rework of the previous PR (#15658).

Commit Message: HCM: protect against removal of critical response headers by a filter chain.
Additional Description: Previously, Envoy hasn't been guarded from the removal of critical response headers like :status. This happens when there's misbehaving filter chan, and especially this protection is important when users run their own extensions through Wasm. Resolves #13756 and ref: #15487.

Notes

  • For the request path, Envoy is already guarded by HeaderUtility::checkRequiredHeaders and its error is gracefully handled in the onPoolReady.

  • The following is the current crash path with uncaught exception caused by removed :status header after filter chains:

chargeStats(headers);

uint64_t response_code = Utility::getResponseStatus(headers);

throw CodecClientException(":status must be specified and a valid unsigned long");

Signed-off-by: Takeshi Yoneda [email protected]

@mathetake mathetake changed the title HCM: protect against removal of critical response headers. HCM: protect against removal of critical response headers by a filter chain. Jun 1, 2021
Signed-off-by: Takeshi Yoneda <[email protected]>
@mathetake mathetake marked this pull request as ready for review June 1, 2021 09:11
mathetake added 2 commits June 1, 2021 18:25
Signed-off-by: Takeshi Yoneda <[email protected]>
Signed-off-by: Takeshi Yoneda <[email protected]>
Copy link
Contributor

@asraa asraa left a comment

Choose a reason for hiding this comment

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

i think my vote for making encodeHeaders (although larger change) return a status is that we won't need to check elsewhere in case some other extension point besides filters break status (i think that was the comment on my request side PR). but maybe that should change when that will be a problem

source/common/http/header_utility.cc Outdated Show resolved Hide resolved
@mathetake mathetake requested a review from asraa June 1, 2021 12:48
@mathetake
Copy link
Member Author

we won't need to check elsewhere in case some other extension point besides filters break status

Thanks, that makes sense.. but yeah we could expand this check when actually we see other extension points break the status header.

asraa
asraa previously approved these changes Jun 1, 2021
Copy link
Contributor

@asraa asraa left a comment

Choose a reason for hiding this comment

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

The code otherwise looks good to me, deferring to a senior maintainer for any opinions on the approach
@envoyproxy/senior-maintainers

test/common/http/utility_test.cc Outdated Show resolved Hide resolved
Signed-off-by: Takeshi Yoneda <[email protected]>
Signed-off-by: Takeshi Yoneda <[email protected]>
Copy link
Contributor

@alyssawilk alyssawilk left a comment

Choose a reason for hiding this comment

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

thanks for fixing this.

LGTM modulo comment request.

Non-blocking comments, fixing this crash is good, but if we want to allow semi-trusted wasm, I think we should do the full suite of header checks that we do in the codec after wasm runs, ensure all headers only have valid characters, we don't allow smuggling by having transfer encoding and content length, relative urls don't start with ../ etc? Is there a plan and/or tracking issue for that?

source/common/http/header_utility.cc Show resolved Hide resolved
* Required request headers include :method header, :path for non-CONNECT requests, and
* host/authority for HTTP/1.1 or CONNECT requests.
* @return Status containing the result. If failed, message includes details on which header was
* missing.
*/
static Http::Status checkRequiredHeaders(const Http::RequestHeaderMap& headers);
static Http::Status checkRequiredRequestHeaders(const Http::RequestHeaderMap& headers);
Copy link
Contributor

Choose a reason for hiding this comment

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

I hear your point about calling this from the codec being really messy.
optional!: Could we at least as part of this PR make the codecs not throw/crash if they get bad data a well? I think we'd prefer to serialize 0 if status code is not present to crashing though Matt may disagree =P

Copy link
Member Author

Choose a reason for hiding this comment

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

In order to do so, we should eliminate all the usage of getResponseStatus and use getResponseStatusNoThrow instead? e.g.

I think fixing this is worth a separate PR and discussion, so can I open an issue for now and discuss there?

Copy link
Contributor

Choose a reason for hiding this comment

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

SGTM, and as it's optional don't feel obliged to tackle it (though it would be nice!)
I think it's largely a part of removing exceptions from the data plane, which I think @chaoqin-li1123 is looking at

@mathetake
Copy link
Member Author

but if we want to allow semi-trusted wasm, I think we should do the full suite of header checks that we do in the codec after wasm runs, ensure all headers only have valid characters, we don't allow smuggling by having transfer encoding and content length, relative urls don't start with ../ etc? Is there a plan and/or tracking issue for that?

yeah that's true and this is somewhat related to the comment by @PiotrSikora #15487 (comment), and yes, we should do Wasm specific check in addition to this Envoy-wide protection. I will open an issue for tracking this. Thanks!

@mathetake mathetake requested a review from alyssawilk June 2, 2021 00:43
@alyssawilk alyssawilk merged commit 13f1860 into envoyproxy:main Jun 2, 2021
@mathetake mathetake deleted the missing-response-headers branch June 2, 2021 23:08
leyao-daily pushed a commit to leyao-daily/envoy that referenced this pull request Sep 30, 2021
… chain. (envoyproxy#16745)

This is the rework of the previous PR (envoyproxy#15658).

Additional Description: Previously, Envoy hasn't been guarded from the removal of critical response headers like :status. This happens when there's misbehaving filter chan, and especially this protection is important when users run their own extensions through Wasm. Resolves envoyproxy#13756 and ref: envoyproxy#15487.
Testing: new integration tests
Risk: low

Signed-off-by: Takeshi Yoneda <[email protected]>
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.

Gracefully handle removal of critical headers by filters
3 participants