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
Improve handling of expanding HTTP header values #1536
Improve handling of expanding HTTP header values #1536
Conversation
Squid manipulations often increase HTTP header value length compared to the corresponding raw value received by Squid. Raw header length is checked against request_header_max_size and reply_header_max_size that default to 64KB, making the raw value safe to store in a String object (by default). However, when the increased length of a manipulated value exceeds String class limits, Squid leaks memory, asserts, or possibly stalls affected transactions. The long-term fix for this problem is a complete String elimination from Squid sources, but that takes time. Known manipulations may effectively concatenate headers and/or increase header value length by 50%. This workaround makes such known increases safe by essentially tripling String class limits: (64KB + 64KB) * 150% = 3 * 64KB This bug was discovered and detailed by Joshua Rogers at https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html where it was filed as "Memory Leak in HTTP Response Parsing".
// headers. Technically, we do not concatenate _requests_, so we could relax | ||
// their check, but we keep the two checks the same for simplicity sake. | ||
const auto safeRawHeaderValueSizeMax = (String::SizeMaxXXX()+1)/3; | ||
// TODO: static_assert(safeRawHeaderValueSizeMax >= 64*1024); // no WARNINGs for default settings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String::SizeMaxXXX() is not constexpr, so we cannot use static_assert() here without more out-of-scope changes. I do not insist on adding this commented-out assertion. Please let me know whether you would prefer this comment gone or those constexpr changes added instead of the current state.
/// convert them to canonical form. The new limit is selected to withstand | ||
/// concatenation and ~50% expansion of two HTTP headers limited by default | ||
/// request_header_max_size and reply_header_max_size settings. | ||
static const size_type SizeMax_ = 3*64*1024 - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new comment states that we do not know where those "some fixed-size buffers" are or whether they exist. I could not find such buffers. To qualify, a buffer would have to meet these two criteria:
- Be problem-free when SizeMax_ remains at the official 64KB setting
- Become problematic when SizeMax_ increases
If you know where such buffers are in the current official Squid code, please share that information. In that case, this PR may need more work to accommodate those buffers!
if (!strFwd.canGrowBy(strFwd.size())) { | ||
// Detect unreasonably long header values. And paranoidly check String | ||
// limits: a String ought to accommodate two reasonable-length values. | ||
if (strFwd.size() > 32*1024 || !strFwd.canGrowBy(strFwd.size())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change preserves existing limits for forwarding loop detection. IMO, there is no reason to increase those limits (i.e. there is no reason to allow even longer forwarding loops just because we are not going to crash if we allow them).
The approach looks like a sensible patch; has it been tested in any way? |
Yes, of course. All PRs are supposed to be tested unless noted otherwise. Factory PRs, including this one, follow that rule. Needless to say, it is not feasible to test all code paths affected by this change in the maximum String buffer size. Besides testing, I did try to find all limit users, and analyzed the ones I found. We plan to add the corresponding CI regression tests, but fixing other Zero Day vulnerabilities with published reproducers takes priority. |
Squid manipulations often increase HTTP header value length compared to the corresponding raw value received by Squid. Raw header length is checked against request_header_max_size and reply_header_max_size that default to 64KB, making the raw value safe to store in a String object (by default). However, when the increased length of a manipulated value exceeds String class limits, Squid leaks memory, asserts, or possibly stalls affected transactions. The long-term fix for this problem is a complete String elimination from Squid sources, but that takes time. Known manipulations may effectively concatenate headers and/or increase header value length by 50%. This workaround makes such known increases safe by essentially tripling String class limits: (64KB + 64KB) * 150% = 3 * 64KB This bug was discovered and detailed by Joshua Rogers at https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html where it was filed as "Memory Leak in HTTP Response Parsing".
Squid manipulations often increase HTTP header value length compared to the corresponding raw value received by Squid. Raw header length is checked against request_header_max_size and reply_header_max_size that default to 64KB, making the raw value safe to store in a String object (by default). However, when the increased length of a manipulated value exceeds String class limits, Squid leaks memory, asserts, or possibly stalls affected transactions. The long-term fix for this problem is a complete String elimination from Squid sources, but that takes time. Known manipulations may effectively concatenate headers and/or increase header value length by 50%. This workaround makes such known increases safe by essentially tripling String class limits: (64KB + 64KB) * 150% = 3 * 64KB This bug was discovered and detailed by Joshua Rogers at https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html where it was filed as "Memory Leak in HTTP Response Parsing".
queued for backport to v6 |
Squid manipulations often increase HTTP header value length compared to the corresponding raw value received by Squid. Raw header length is checked against request_header_max_size and reply_header_max_size that default to 64KB, making the raw value safe to store in a String object (by default). However, when the increased length of a manipulated value exceeds String class limits, Squid leaks memory, asserts, or possibly stalls affected transactions. The long-term fix for this problem is a complete String elimination from Squid sources, but that takes time. Known manipulations may effectively concatenate headers and/or increase header value length by 50%. This workaround makes such known increases safe by essentially tripling String class limits: (64KB + 64KB) * 150% = 3 * 64KB This bug was discovered and detailed by Joshua Rogers at https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html where it was filed as "Memory Leak in HTTP Response Parsing".
Squid manipulations often increase HTTP header value length compared to the corresponding raw value received by Squid. Raw header length is checked against request_header_max_size and reply_header_max_size that default to 64KB, making the raw value safe to store in a String object (by default). However, when the increased length of a manipulated value exceeds String class limits, Squid leaks memory, asserts, or possibly stalls affected transactions. The long-term fix for this problem is a complete String elimination from Squid sources, but that takes time. Known manipulations may effectively concatenate headers and/or increase header value length by 50%. This workaround makes such known increases safe by essentially tripling String class limits: (64KB + 64KB) * 150% = 3 * 64KB This bug was discovered and detailed by Joshua Rogers at https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html where it was filed as "Memory Leak in HTTP Response Parsing".
Squid manipulations often increase HTTP header value length compared to the corresponding raw value received by Squid. Raw header length is checked against request_header_max_size and reply_header_max_size that default to 64KB, making the raw value safe to store in a String object (by default). However, when the increased length of a manipulated value exceeds String class limits, Squid leaks memory, asserts, or possibly stalls affected transactions. The long-term fix for this problem is a complete String elimination from Squid sources, but that takes time. Known manipulations may effectively concatenate headers and/or increase header value length by 50%. This workaround makes such known increases safe by essentially tripling String class limits: (64KB + 64KB) * 150% = 3 * 64KB This bug was discovered and detailed by Joshua Rogers at https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html where it was filed as "Memory Leak in HTTP Response Parsing".
Squid manipulations often increase HTTP header value length compared to
the corresponding raw value received by Squid. Raw header length is
checked against request_header_max_size and reply_header_max_size that
default to 64KB, making the raw value safe to store in a String object
(by default). However, when the increased length of a manipulated value
exceeds String class limits, Squid leaks memory, asserts, or possibly
stalls affected transactions. The long-term fix for this problem is a
complete String elimination from Squid sources, but that takes time.
Known manipulations may effectively concatenate headers and/or increase
header value length by 50%. This workaround makes such known increases
safe by essentially tripling String class limits:
This bug was discovered and detailed by Joshua Rogers at
https://megamansec.github.io/Squid-Security-Audit/response-memleaks.html
where it was filed as "Memory Leak in HTTP Response Parsing".