-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
deflate bug with windowBits == 8? #171
Comments
Yes. |
Is this something that can be fixed? Does this mean that all existing implementations of WebSocket permessage-deflate are also broken (since they all use ZLib, and they can negotiate an 8-bit window)? |
Perhaps it can be fixed, but I have not tried. Nothing should be broken, since an 8-bit window zlib stream is never generated by zlib. If 8 is requested, a 9-bit window is used instead. |
Here's the possible issue, a WebSocket client requests an 8-bit window. The server (using ZLib, and unaware of line 276 in deflate.c) agrees, and responds that it will use an 8-bit window. At this point the server will compress data, and that data may contain match offsets greater than 256 (since its really using a 9 bit window). The client will receive that data and get this error: |
In addition to compressing with a 512-byte window, 9 bits is put in the zlib header when 8 bits is requested. So zlib, or any compliant decompressor reading that header, will use at least a 512-byte window and there will be no error on decompression. |
That is certainly true if you are using a zlib header, but the WebSocket protocol specifies raw deflate streams and negotiates the window sizes separately in the HTTP request/response sequence which initiates the session: I believe all existing WebSocket implementations that use ZLib are vulnerable to this bug. Take websocketpp for example: If a client requests an 8-bit window size, the server will call |
You are correct. I have committed 049578f to reject requests for a window size of 256 bytes when using raw or gzip encoding. |
Should this be reported in a security advisory? |
What's the "exploit" here? Is it simply that things "fail to work correct" if 8 (rather than 9) is passed? Or can this lead to a crash on the server-side if the wrong window is used (therefore there's a potential DoS)? I'd also say that this wasn't a security issue for zlib, but a security issue for, e.g., websocketpp. |
I don't know that it leads to a crash for a well written server, but for an application which uses raw deflate, if the application calls Whether or not its a denial of service depends on if the application handles errors correctly. |
Quite, so this seems like an "API usage error". There's no security vulnerability with zlib itself, but there are potential usage scenarios when something depending on zlib could call it in an incorrect way and get "unexpected" results. For example, for websocketpp, what does the server do if it hits that error? I assume that it checks that return code for Honestly, I don't really understand if there's a wider implication; my assumption is though that there's nothing serious here (e.g., like Heartbleed) -- if zlib simply processed the mis-matched window and then returned non-controlled data, then there might be an issue. As it is, zlib appears to do do some sanity checking, and returns an error on "bad" data. Nothing untoward seems like it has happening there. Without trying it, I presume that: https://github.com/madler/zlib/blob/master/inflate.c#L1249 gets hit and returns Z_BUF_ERROR. It is up to the caller to check the return code and handle that sensibly. If websocketpp doesn't handle that sensibly, and does something else, then there could be a security implication there. |
Your analysis is sound |
The server_max_window_bits value sent by the client in the negotiation offer is used to configure the deflater on the server. This acceptance is also notified to the client by returning the server_max_window_bits header in the negotiation response. A special case arises when we receive server_max_window_bits = 8. There's an open zlib issue with the window size of 8. For zlib streams, the library silently changes the window size to 9 and informs the inflater via the zlib header. However, this apparent hack is not feasible for raw deflate streams, which are used in WebSockets. To take care of this fact, zlib has been patched to reject a window size of 8, via a deflateInit2() failure. Details here: madler/zlib#171 As a result, we need to handle a window size request of 8 as a special case. We silently change it to 9 and inform the client via a suitable header in the negotiation response.
The server_max_window_bits value sent by the client in the negotiation offer is used to configure the deflater on the server. This acceptance is also notified to the client by returning the server_max_window_bits header in the negotiation response. A special case arises when we receive server_max_window_bits = 8. There's an open zlib issue with the window size of 256 (windoBits=8). For zlib streams, the library silently changes the windowBits to 9 and informs the inflater via the zlib header. However, this apparent hack is not feasible for raw deflate streams, which are used in WebSockets. To take care of this fact, zlib has been patched to reject a window size of 256, via a deflateInit2() failure. Details here: madler/zlib#171 As a result, we need to handle a window size of 256 (windowBits=8) as a special case. We silently change it to 9 and inform the client via a suitable header in the negotiation response.
* permessage-deflate: implement context takeover * Use negative windowBits values for the deflater The compression format of the output produced by zlibs deflater is decided by the windowBits values it is configured with. We used positive windowBits values which, according to the zlib manual, emits the zlib stream starting with a zlib header. WebSockets use raw deflate streams, and not zlib streams. Consequently, we had to strip the zlib header. The deflater can be configured to emit a raw deflate format by using negative values for the windowBits. With this in place, there's no zlib header in the output stream. * Handle the special case of LZ77 window size of 256 The server_max_window_bits value sent by the client in the negotiation offer is used to configure the deflater on the server. This acceptance is also notified to the client by returning the server_max_window_bits header in the negotiation response. A special case arises when we receive server_max_window_bits = 8. There's an open zlib issue with the window size of 256 (windoBits=8). For zlib streams, the library silently changes the windowBits to 9 and informs the inflater via the zlib header. However, this apparent hack is not feasible for raw deflate streams, which are used in WebSockets. To take care of this fact, zlib has been patched to reject a window size of 256, via a deflateInit2() failure. Details here: madler/zlib#171 As a result, we need to handle a window size of 256 (windowBits=8) as a special case. We silently change it to 9 and inform the client via a suitable header in the negotiation response. * Close deflater and inflater streams on connection close Without context takeover, the deflater and inflater are initialized and closed on every message. However, with context takeover, the deflater and inflater persist for the entire lifetime of the connection. They need to be closed on a connection close. The deflater is on a ChannelOutboundHandler and must be closed when the WebSocketConnections issues a channel.close(). The inflater is on a ChannelInboundHandler, it must be closed when we receive a `closeConnection` frame from the remote peer.
For 64bit armv8-a there's no need to use "-mfpu=neon" to enable NEON. But for 32bit system "-mfpu=neon" is required. This patch adds the detection for -mfpu=neon flag. Signed-off-by: Richael Zhuang [email protected]
I think it’s wrong to leave it as it is. It's necessary to denide the use of a 256 byte window for both compression and decompression. This will be more correct since compression with this window is not supported. |
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
This is specifically to deal with the case whereby the window size is set to 8. As zlib dropped support for 256 (8 bit) window sizes in 1.2.9, https://www.zlib.net/ChangeLog.txt, onwards. 8 bit windows were broken before as well, madler/zlib#171. As autobahn tests 8 bit windows the tox test would fail based on the zlib version installed - hence the relevant autobahn tests are also disabled. 8 bit windows are rarely used in practice, so this should be ok practically. If not zlib needs to be fixed, see madler/zlib#87 (comment)
What's all this about?
https://github.com/madler/zlib/blob/master/deflate.c#L276
Does this mean that 256-byte windows are broken?
The text was updated successfully, but these errors were encountered: