Headline
CVE-2023-38697: Strict validation of content length and chunk length. by ioquatix · Pull Request #20 · socketry/protocol-http1
protocol-http1 provides a low-level implementation of the HTTP/1 protocol. RFC 9112 Section 7.1 defined the format of chunk size, chunk data and chunk extension. The value of Content-Length header should be a string of 0-9 digits, the chunk size should be a string of hex digits and should split from chunk data using CRLF, and the chunk extension shouldn’t contain any invisible character. However, Falcon has following behaviors while disobey the corresponding RFCs: accepting Content-Length header values that have +
prefix, accepting Content-Length header values that written in hexadecimal with 0x
prefix, accepting 0x
and +
prefixed chunk size, and accepting LF in chunk extension. This behavior can lead to desync when forwarding through multiple HTTP parsers, potentially results in HTTP request smuggling and firewall bypassing. This issue is fixed in protocol-http1
v0.15.1. There are no known workarounds.
Security researchers @mukeran and @chenjj have reported issues with parsing content length and chunk lengths:
RFC 9112 Section 7.1 defined the format of chunk size, chunk data and chunk extension (detailed ABNF is in Appendix secion).
In a word:
- The value of Content-Length header should be a string of 0-9 digits.
- The chunk size should be a string of hex digits and should split from chunk data using CRLF.
- The chunk extension shouldn’t contain any invisible character.
However, we found that Falcon has following behaviors while disobey the corresponding RFCs.
- Falcon accepts Content-Length header values that have “+” prefix.
- Falcon accepts Content-Length header values that written in hexadecimal with “0x” prefix.
- Falcon accepts “0x” and “+” prefixed chunk size.
- Falcon accepts LF in chunk extension.
This behavior can lead to desync when forwarding through multiple HTTP parsers, potentially results in HTTP request smuggling and firewall bypassing.
When sending the following requests to the server, falcon successfully parsed our requests and our application successfully read request body.
Impact
The above is a valid assessment of the behaviour of the HTTP/1 parser. However, as this gem does not expose the raw body or forward it in any way, I don’t believe it can cause issues in the real world. However, I accept that stricter parsing of the length fields is a good idea.
Regarding chunk extensions, these are ignored and not exposed to the user. Therefore, I don’t believe it would be valuable to validate these. Feel free to correct me here.
Actions
- Adopt stricter parsing of the content length field according to the RFC.
- Adopt stricter parsing of the chunk length according to the RFC.
- Explicitly ignore any chunk extension fields.
Types of Changes
- Security
Contribution
- I added tests for my changes.
- I tested my changes locally.
- I agree to the Developer’s Certificate of Origin 1.1.
Related news
### Impact [RFC 9112 Section 7.1](https://www.rfc-editor.org/rfc/rfc9112#name-chunked-transfer-coding) defined the format of chunk size, chunk data and chunk extension (detailed ABNF is in Appendix section). In summary: - The value of Content-Length header should be a string of 0-9 digits. - The chunk size should be a string of hex digits and should split from chunk data using CRLF. - The chunk extension shouldn't contain any invisible character. However, we found that Falcon has following behaviors while disobey the corresponding RFCs. - Falcon accepts Content-Length header values that have "+" prefix. - Falcon accepts Content-Length header values that written in hexadecimal with "0x" prefix. - Falcon accepts "0x" and "+" prefixed chunk size. - Falcon accepts LF in chunk extension. This behavior can lead to desync when forwarding through multiple HTTP parsers, potentially results in HTTP request smuggling and firewall bypassing. Note that while these issues were reproduced in Fa...