Bug #7285
openWebsocket compression mishandling
Description
There are a number of problems with the decompression implementation of WebSockets. Firstly, in the example PCAP every individual transaction is comprised of a single frame, which fails (https://github.com/OISF/suricata/blob/089d2b1/rust/src/websocket/websocket.rs#L202) because the buffer is empty and the fin flag is set, therefore the path is never executed and for the same reason its not marked as compressed.
Now the other problem is with the LZ77 sliding window (https://datatracker.ietf.org/doc/html/rfc7692#section-7.2.2). In this case the Sec-WebSocket-Extensions negotiate a client_max_window_bits=15, but this is not followed in the decompression, resulting in the situations in the screenshot where blocks of data are missing (only after marking every frame as compressed).
Lastly, it doesn't seem like there is any handling on decompression limits with the DeflateDecoder, despite the default WEBSOCKET_MAX_PAYLOAD_SIZE of size 0xffff (which can be increased by users), 65kb is probably enough to have a decent deflate bomb (it seems the limit is ~1032 * 0xffff ~ 67mb).
A python example that handles the decompression properly:
import zlib
leader = "0000ffff"
pkts = ["f2768db435304f4eb23435b54c4d4b33324c354e353649334e4a4a31b4303231484a4c360600", "0af17777f771b5354ab1304832324a4d49324e4c4b0600", "820a9a9ba59898a65aa4a6a4261a1ba40100"]
client_max_window_bits = 15
c = zlib.decompressobj(-client_max_window_bits)
for p in pkts:
print(c.decompress(bytes.fromhex(p + leader)))
Files
No data to display