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

Fix bypassing Request Body scanning with trailers #288

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

iosetek
Copy link

@iosetek iosetek commented Aug 2, 2024

The present implementation of WASM plugin is missing a scenario that onRequestBody method will never be called with end_of_stream parameter set to true. Such situation will happen for HTTP 2 request with trailers as the presence of trailers means that the last chunk of payload is still not the end of the request stream.

This is problematic because existing implementation triggers threat scanning when onRequestBody is called with parameter end_of_stream set to true as it was expected to be a proper place:

  • right after collecting entire payload

  • before completing the request stream

This is true only for scenarios that do NOT include request trailers (unless it is HTTP1 as Envoy Proxy ignores request trailers for that protocol - the explanation is that trailers in HTTP1 are very often not handled properly by various servers even though HTTP standard allows it).

To fix it, onRequestTrailers method was implemented to cover the situation when request payload was collected as onRequestTrailers is the method which applies to the situation:

  • right after collecting entire payload

  • before completing the request stream

To maintain the existing logic, this method calls onRequestBody with end_of_stream set to true, to share the same logic.

The onResponseTrailers method was not implemented but perhaps it should be implemented as well.

The present implementation of WASM plugin is missing a scenario
that onRequestBody method will never be called with end_of_stream
parameter set to true. Such situation will happen for HTTP 2
request with trailers as the presence of trailers means that the
last chunk of payload is still not the end of the request stream.

This is problematic because existing implementation triggers
threat scanning when onRequestBody is called with parameter
end_of_stream set to true as it was expected to be a proper place:

* right after collecting entire payload

* before completing the request stream

This is true only for scenarios that do NOT include request trailers
(unless it is HTTP1 as Envoy Proxy ignores request trailers for that
protocol - the explanation is that trailers in HTTP1 are very often
not handled properly by various servers even though HTTP standard
allows it).

To fix it, onRequestTrailers method was implemented to cover the
situation when request payload was collected as onRequestTrailers
is the method which applies to the situation:

* right after collecting entire payload

* before completing the request stream

To maintain the existing logic, this method calls onRequestBody
with end_of_stream set to true, to share the same logic.

The onResponseTrailers method was not implemented but perhaps
it should be implemented as well.
@iosetek iosetek force-pushed the fix-bypassing-request-body-scanning branch from 9a5fadc to 7d46156 Compare August 2, 2024 16:06
Copy link
Member

@M4tteoP M4tteoP 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 the very detailed issue/PR. Writing a few initial comments, I will take a deep look at it as soon as possible over the weekend.

Also, would you think is possible to have a smaller reproducer that can fit go tests or, eventually, an e2e?

The end_of_stream parameter definition may be unclear - it is set to
true if:
* there are no more payload chunks to process
* there are no HTTP trailers
Copy link
Member

@M4tteoP M4tteoP Aug 2, 2024

Choose a reason for hiding this comment

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

I'm aware of the convoluted (and lack of) documentation, but by any chance, do you have any reference about this? I just found these lines that might be making me think in that direction: https://github.com/proxy-wasm/spec/pull/42/files#diff-39c0fcbaec7f6ffb311e442b6f0774bf3c050cd9b3318f51f55c2d6c38d4976dR609-R610, but any reference to docs/code would be great

Copy link
Member

Choose a reason for hiding this comment

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

Comment on lines +455 to +458
// If no payload was collected so far, then there is nothing to do.
if ctx.bodyReadIndex == 0 {
return types.ActionContinue
}
Copy link
Member

Choose a reason for hiding this comment

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

I would delegate that decision to the existing logic by also calling in that case ctx.OnHttpRequestBody.
If I'm getting this right, OnHttpRequestTrailers is going to be called just once and it will happen after all the OnHttpRequestBody calls. So, from a Coraza point of view, what we have to do now is process phase:2 rules independently from the fact that they will analyze the payload or not.

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.

2 participants