Bandit WebSocket permessage-deflate unbounded inflate leads to DoS
Bandit versions 0.5.8 before 1.11.0 are vulnerable to denial of service when permessage-deflate is enabled, allowing an unauthenticated client to exhaust the BEAM's memory with a single, small, compressed WebSocket frame due to unbounded decompression.
Bandit, a web server for the Erlang ecosystem, is vulnerable to a denial-of-service (DoS) attack. The vulnerability exists in versions 0.5.8 before 1.11.0 when the permessage-deflate WebSocket extension is enabled. An unauthenticated client can send a small, specially crafted compressed WebSocket frame that, when decompressed, expands to a significantly larger size, exhausting the server’s memory. This occurs because the inflate step within Bandit lacks an output-size cap. This vulnerability affects applications that have explicitly enabled compress: true when upgrading a connection to a WebSocket, as stock Phoenix and LiveView apps default to compress: false. The attack occurs before any application-level code execution, making it difficult to mitigate without patching the Bandit library itself.
Attack Chain
- An unauthenticated client establishes a TCP connection to the Bandit server.
- The client sends a WebSocket handshake request with
Sec-WebSocket-Extensions: permessage-deflate. - The Bandit server negotiates the
permessage-deflateextension if bothwebsocket_options.compressandconnection_opts.compressare true. - The client sends a WebSocket text frame with the RSV1 bit set to 1, indicating compressed data. The compressed frame is crafted to have a high compression ratio (e.g., 1024:1).
- The Bandit server receives the compressed frame and begins decompression using
:zlib.inflate/2inlib/bandit/websocket/permessage_deflate.ex. - The inflation process lacks any output-size limit, allowing the decompressed data to grow unbounded in memory.
IO.iodata_to_binary/1materializes the entire decompressed payload into a single binary in the connection process’s heap.- The server exhausts its available memory, leading to a denial-of-service condition as the BEAM process is OOM-killed or becomes unresponsive.
Impact
Successful exploitation results in a denial-of-service condition, potentially crashing the BEAM and rendering the Bandit-fronted application unavailable. A single, small compressed frame (~6MiB in the provided PoC) is sufficient to trigger the vulnerability, and concurrent connections will amplify the impact linearly. Applications that have enabled permessage-deflate for bandwidth savings are particularly at risk, as they may not be aware of the inherent unbounded-inflate DoS. This can affect any service using Bandit webserver which explicitly enables the compress option, leading to potential service outages.
Recommendation
- Disable the
compress: trueoption when callingWebSockAdapter.upgrade/4as a temporary workaround to mitigate the vulnerability. - Monitor process memory usage on systems running Bandit web servers, looking for sudden and significant increases, particularly after WebSocket connections are established. Consider creating a Sigma rule for this behavior based on process memory metrics.
- Upgrade to Bandit version 1.11.0 or later once available to address the vulnerability with the fix suggested: “thread a maximum-output-size through to inflate and either error out or return resumable chunks once exceeded, mirroring how the HTTP content-length path bounds reads via
:length.”. - Deploy the Sigma rule detecting WebSocket handshake with
permessage-deflateto identify potentially vulnerable configurations.
Detection coverage 3
Detect WebSocket Handshake with permessage-deflate
mediumDetects WebSocket handshake requests that include the 'permessage-deflate' extension, indicating a potentially vulnerable configuration if compression is enabled.
Detect High BEAM Memory Usage
lowDetects unusually high BEAM memory usage, potentially indicating a memory exhaustion attack related to the permessage-deflate vulnerability in Bandit.
Detect Bandit permessage-deflate option enabled
infoDetects when the Bandit option permessage-deflate is enabled by looking for compress: true in the websocket options.
Detection queries are kept inside the platform. Get full rules →