Headline
CVE-2023-27492: Crash when a large request body is processed in Lua filter
Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to versions 1.26.0, 1.25.3, 1.24.4, 1.23.6, and 1.22.9, the Lua filter is vulnerable to denial of service. Attackers can send large request bodies for routes that have Lua filter enabled and trigger crashes. As of versions versions 1.26.0, 1.25.3, 1.24.4, 1.23.6, and 1.22.9, Envoy no longer invokes the Lua coroutine if the filter has been reset. As a workaround for those whose Lua filter is buffering all requests/ responses, mitigate by using the buffer filter to avoid triggering the local reply in the Lua filter.
Impact
Denial of service (crash).
Affected components
Lua filter.
Attack vector/s
Attackers can send large request bodies for routes that have Lua filter enabled and trigger crashes.
Description
The Lua filter can resume processing of the coroutine after we’ve sent a local reply due to request/response body being too large. This mitigation prevents coroutine invocation if we’re doing a local reply.
Example exploit or proof-of-concept
1 Configure a route that has Lua filter enabled.
2 Send a request with a large body that is beyond the buffer limit.
3 Have the Lua script request the request body, this will cause us to buffer the entire request body.
4 The request body buffering can go over the limit here: https://sourcegraph.com/github.com/envoyproxy/envoy@991cde892ff88b7aca04adb7fc44e14f6c0ee0fe/-/blob/source/extensions/filters/http/lua/lua_filter.cc?L263&subtree=true#tab=references and send the local reply, but the Lua filter is oblivious and continues the coroutine.
5 The Lua script kicks off a HTTP request that points to the Lua filter.
6 The Lua filter is destroyed as Envoy has completed the local reply and destroyed the related objects.
7 The HTTP request that the Lua script kicked off in step 5 has a response, and calls the Lua filter. The filter will already be destroyed, so Envoy will segfault.
Detection
Given enough traffic of this type, Envoy would be crashing especially when the body buffered is larger.
Mitigation
For versions updated with the patch, we no longer invoke the Lua coroutine if the filter has been reset.
For older unpatched versions you can mitigate by:
If your Lua filter is buffering all requests/ responses you can guard by using the buffer filter to avoid triggering the local reply in the Lua filter.
Discoverer/credit
Dan Tulovsky [email protected]
Related news
Red Hat Security Advisory 2023-4623-01 - Red Hat OpenShift Service Mesh is Red Hat's distribution of the Istio service mesh project, tailored for installation into an OpenShift Container Platform installation.
Red Hat OpenShift Service Mesh 2.2.9 Red Hat Product Security has rated this update as having a security impact of Important. A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE link(s) in the References section.This content is licensed under the Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). If you distribute this content, or a modified version of it, you must provide attribution to Red Hat Inc. and provide a link to the original. Related CVEs: * CVE-2023-27487: A flaw was found in envoy. The header x-envoy-original-path should be an internal header, but Envoy does not remove this header from the request at the beginning of request processing when it is sent from an untrusted client. The faked header could then be used for trace logs and grpc logs, used in the URL for jwt_authn checks if the jwt_authn filter is used, and any other upstr...
gRPC contains a vulnerability that allows hpack table accounting errors could lead to unwanted disconnects between clients and servers in exceptional cases/ Three vectors were found that allow the following DOS attacks: - Unbounded memory buffering in the HPACK parser - Unbounded CPU consumption in the HPACK parser The unbounded CPU consumption is down to a copy that occurred per-input-block in the parser, and because that could be unbounded due to the memory copy bug we end up with an O(n^2) parsing loop, with n selected by the client. The unbounded memory buffering bugs: - The header size limit check was behind the string reading code, so we needed to first buffer up to a 4 gigabyte string before rejecting it as longer than 8 or 16kb. - HPACK varints have an encoding quirk whereby an infinite number of 0’s can be added at the start of an integer. gRPC’s hpack parser needed to read all of them before concluding a parse. - gRPC’s metadata overflow check was performed per frame, so ...