-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Request body doubly written to upstream with file system buffer filter #39139
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
Comments
I think this is a misbehavior of retries rather than a misbehavior of the filter - i.e. HTTP filters expect that decodeHeaders will be called once, and decodeData will be called enough times for the data to pass through once, but I think what's happening here is that a retry causes all the filters to run again, with their state intact, with all the inputs from a request that has already been processed by the filter being passed in. Which is two things wrong - if a filter is stateless, on retry it still ends up doing its action on an already-modified request, e.g. a MutateHeaders filter with an 'add' mode mutation would end up, after a retry, with the upstream receiving the same header twice (or more). The latter could be fixed by instantiating a new filter chain for retries rather than reusing the existing filter chain, but the former would still be problematic IMO. It's also possible that I'm wrong and HTTP filter instances are supposed to be stateless or only capture their state in a special way that's initialized per request, in which case the first problem still seems problematic, but that would make the second case an issue to be addressed in the buffer filter (and probably several other filters). I don't think that's the case, though I think maybe some years ago HTTP filters operated that way, and the misbehavior of retries might be an accidental holdover from that time. If I'm right about how it's supposed to work, then I would suggest that Edit: and I don't even have a good idea for how to address the "non-idempotent filters applied twice" problem. |
@ravenblackx One thing I forgot to highlight in the description is that this issue is reproducible in the presence of a retry policy, even if |
But not reproducible in the absence of a retry policy, right? So now it sounds like two bugs in the retry behavior, in that if |
@ravenblackx Yes-- if we remove the retry policy, Envoy's behavior is correct. |
To clarify, the security impact here not only includes the behavior described above, but also the attacker recieves responses intended for other users. This would include sesson cookies or other secrets. |
Unfortunately it seems we no longer have anyone whose specialist subject includes retries - I've ended up assigned as one of the codeowners for that area because I'm willing to review, but I'm not going to have time to try to fix this, and the other codeowner for retries is @mattklein123 who I'm pretty sure also doesn't have time to dedicate to it. [correct me if I'm wrong Matt] So there are three options remaining:
Specifically, I think this could be worked around by changing the config from
to
I realize this is a horrible solution and leaves the underlying bug intact, but it could at least unblock you. |
@yanavlasov @botengyao for maybe additional thoughts on security implications. I don't know if we'd want to maybe document somewhere "mixing retries with other filters has unpleasant security implications", if we can't get it fixed. |
This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or "no stalebot" or other activity occurs. Thank you for your contributions. |
Uh oh!
There was an error while loading. Please reload this page.
If you are reporting any crash or any potential security issue, do not open an issue in this repo. Please report the issue via emailing envoy-security@googlegroups.com where the issue will be triaged appropriately.
Title: Request body doubly written to upstream with file system buffer filter
Description:
We have observed the following unexpected behavior:
When a retry policy is added to a route for a listener configured with file system buffer filter, Envoy would write the request body twice to the upstream connection. (Removing either the retry policy or the file system buffer filter will result in expected behavior of Envoy.)
The echo server reads
Content-Length
from the socket for the request body, leaving the other copy of the request payload in the socket.The remainder bytes of the duplicated payload would be read as prefix to the subsequent request via the same connection (observed as prefix to the request method of the subsequent request in the response from the echo server):
It is possible to forge a request ( as in forged request) whose payload is a different, well-formed request ( as in request in payload). In such cases, we've observed that the backend server will send 2 responses to Envoy — first then as the duplicated copy of was read as a new, stand-alone request.
From our observation, is ignored in most cases. However, when we blast Envoy with concurrently, and in the meantime, we keep sending a different request ( for control). Occasionally, we would observe that instead of the expected , the client would receive .
Repro steps:
This issue is most easily reproduced on a Kubernetes cluster:
We first deploy all resources to the
leaky-body-repro
namespace:We can now port-forward to the Envoy pod.
kubectl port-forward $(kubectl get pod -l 'app=envoy' -n leaky-body-repro -o jsonpath='{.items[0].metadata.name}') -n leaky-body-repro 8080:80 9901
We can send the following request and verify that the payload of the first request gets leaked as the prefix of the second request:
We can also verify that with this behavior of request body leakage, we could cause to be returned to a client sending :
Admin and Stats Output:
server_info.txt
routes.txt
clusters.txt
stats.txt
Config:
See step 1 in repro steps.
Logs:
envoy.log (access logs not configured from repro config).
Call Stack:
No crash.
Comments:
We are uncertain of the exact security implications with this behavior. However, we speculate that depending on the backend server implementation, a forged request could contain a payload that tricks the backend server into sending a response to a non-suspecting client that could alter its behavior in a way desired by adversary. Thus, we are using this channel to report such an unexpected behavior when the file system buffer works in conjunction with route retry policies.
I have reached out to the Envoy Security channel, where @botengyao mentioned that since the behavior is only reproduceable with the file system buffer filter, the work-in-progress status implies that it will not be covered by the security team. I thus open the issue here.
The text was updated successfully, but these errors were encountered: