Hi,
HAProxy 2.8.2 was released on 2023/08/09. It added 73 new commits
after version 2.8.1.
It's one of these rare moments where I'm happy that we're a bit late on
releases, because it allowed us to include a backport for a vulnerability
reported this morning, saving all of us an extra release!
The high severity issues addressed in this version are the following:
- performing multiple large-header replacements at once can sometimes
overwrite parts of the contents of the headers if header size is
increased. This may happen with the "replace-header" action, when the
buffer gets too fragmented, a temporary one is needed to realign it,
then they are permutted. But if this happens more than once, the
allocated temporary buffer could be the one that had just been used,
where live data will be overwritten but the new ones. This can cause
garbage to appear in headers, and might possibly trigger some asserts
depending on the damage and where this passes. This issue was reported
by Christian Ruppert.
- the H3 decoder used to properly reject malformed header names, but
forgot to do so for header values, as was already done for H2. This
could theoretically be used to attack servers behind, though for this
to happen, one would need to have a QUIC listener and a tool permitting
to send such malformed bytes (not granted).
- the check for invalid characters on content-length header values doesn't
reject empty headers, which can pass through. And since they don't have
a value, they're not merged with next ones, so it is possible to pass
a request that has both an empty content-length and a populated one.
Such requests are invalid and the vast majority of servers will reject
them. But there are certainly still a few non-compliant servers that
will only look at one of them, considering the empty value equals zero
and be fooled with this. Thus the problem is not as much for mainstream
users as for those who develop their own HTTP stack or who purposely use
haproxy to protect a known-vulnerable server, because these ones may be
at risk. This issue was reported by Ben Kallus of Dartmouth College and
Narf Industries. A CVE was filed for this one. There is a work-around,
though: simply rejecting requests containing an empty content-length
header will do the job:
http-request deny if { hdr_len(content-length) 0 }
Then there are a bunch of lower severity ones, particularly:
- the URL fragments (the part that follows '#') are not allowed to be
sent on the wire, and their handling on the server side has long been
ambiguous. Historically most servers would trim them, nowadays with
stronger specification requirements most of them tend to simply reject
the request as invalid. Till now we did neither of these, so they
could appear at the end of the "path" sample fetch contents. It can be
problematic in case path_end is used to route requests. For example,
a rule doing routing "{ path_end .png .jpg }" to a static server could
very well match "index.html#.png". The question of how best to proceed
in this case was asked to other HTTP implementers and the consensus was
clearly that this should be actively rejected, which is even specifically
mandated in certain side-protocol specs. A measurement on haproxy.org
shows that such requests appear at a rate of roughly 1 per million, and
are either emitted by poorly written crawlers that copy-paste blocks of
text, or are sent by vulnerability scanners. Thus a check was added for
this corner case which is now blocked by default. In case anyone would
discover that they're hosting a bogus application relying on this, this
can be reverted using "option accept-invalid-http-request". This issue
was reported by Seth Manesse and Paul Plasil.
- the bwlim filter could cause a spinning loop in process_stream() due
to an expiration timer that was not reset.
- in H3, the FIN bit could be handled before the last frame was processed,
triggering an internal error.
- H3: the presence of a content-length header was not reported internally,
causing the FCGI mux on the backend to stall during uploads from QUIC to
FCGI.
- Lua/queue: some queued items could leak and progressively cause a slowdown
of queue:push().
- listener: the proxy's lock is needed in relax_listener(), otherwise we
risk a deadlock through an ABBA pattern that could happen when a listener
gets desaturated.
- logging too large messages to a ring can cause their loss, due to the
maxlen parameter not being accurately calculated.
- quic: when the free space in the buffer used to redispatch datagrams
wraps at the end, new datagrams may be dropped until it empties, due to
the buffer appearing full. This causes excess retransmits when multiple
connections come from the same IP:port.
- quic: a few issues affect the retry tokens (used when a listener is
under flood): a check was missing on the dcid, which could probably
be used to try to create more than one connection per token; the
internal tick was used for the timestamp used in tokens instead of
the wall-clock time, causing a risk that a token will fail to
validate against another node from the same cluster; finally the
initial vector used for random token generation was not strong
enough. Missing parenthesis in the PTO calculation formula could
possibly result in obscure bugs such as a connection probing
infinitely.
- incomplete log server definitions were added to the global list of
servers, but freed without be delete from the list, which can cause
all sorts of issues and crashes when walking over that list or at
deinit() time.
- cache: s-maxage couldn't override "max-age=0" as it ought to, according
to the standard.
- NUMA topology auto-detection was still active when cpu-map directives
were present, which is contrary to what is documented since cpu-map is
the alternative for the command-line "taskset" utility. This could
result in haproxy running on way more cores than permitted by these
directives (e.g. a full socket).
- server-state: empty and missing state files would report warnings, which
could be numerous on first start when having many backends, complicating
the startup when "zero-warning" is set. Now they will be reported at the
notice level instead, so that users can still fix their config typos,
and warnings will be used for other cases (unreadable, invalid contents
etc).
- server name resolution: a warning would be emitted even when
"init-addr none" was present or when starting with -dr, asking to
explicitly disable resolution, which doesn't make sense and contradicts
the documentation. Now it will remain silent in these two special cases.
The rest is of much lower importance or probability, and the usual DOC, CI
and cleanup stuff. Older versions will follow, reusing this changelog when
it fits.
Thanks to all those who reported issues, tested fixes and helped with the
backports!
Please find the usual URLs below :
Site index : https://www.haproxy.org/
Documentation : https://docs.haproxy.org/
Wiki : https://github.com/haproxy/wiki/wiki
Discourse : https://discourse.haproxy.org/
Slack channel : https://slack.haproxy.org/
Issue tracker : https://github.com/haproxy/haproxy/issues
Sources : https://www.haproxy.org/download/2.8/src/
Git repository : https://git.haproxy.org/git/haproxy-2.8.git/
Git Web browsing : https://git.haproxy.org/?p=haproxy-2.8.git
Changelog : https://www.haproxy.org/download/2.8/src/CHANGELOG
Dataplane API :
https://github.com/haproxytech/dataplaneapi/releases/latest
Pending bugs : https://www.haproxy.org/l/pending-bugs
Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs
Code reports : https://www.haproxy.org/l/code-reports
Latest builds : https://www.haproxy.org/l/dev-packages
Willy
---
Complete changelog :
Amaury Denoyelle (3):
BUG/MEDIUM: quic: consume contig space on requeue datagram
BUG/MINOR: quic: reappend rxbuf buffer on fake dgram alloc error
BUILD: quic: fix wrong potential NULL dereference
Aurelien DARRAGON (21):
BUG/MINOR: tcp_sample: bc_{dst,src} return IP not INT
BUG/MEDIUM: sink: invalid server list in sink_new_from_logsrv()
BUG/MINOR: http_ext: unhandled ERR_ABORT in proxy_http_parse_7239()
BUG/MINOR: sink: missing sft free in sink_deinit()
BUG/MINOR: ring: size warning incorrectly reported as fatal error
BUG/MINOR: ring: maxlen warning reported as alert
BUG/MINOR: log: LF upsets maxlen for UDP targets
MINOR: sink/api: pass explicit maxlen parameter to sink_write()
BUG/MEDIUM: log: improper use of logsrv->maxlen for buffer targets
BUG/MINOR: log: fix missing name error message in cfg_parse_log_forward()
BUG/MINOR: log: fix multiple error paths in cfg_parse_log_forward()
BUG/MINOR: log: free errmsg on error in cfg_parse_log_forward()
BUG/MINOR: sink: invalid sft free in sink_deinit()
BUG/MINOR: sink: fix errors handling in cfg_post_parse_ring()
BUG/MINOR: server: set rid default value in new_server()
MINOR: hlua_fcn/mailers: handle timeout mail from mailers section
BUG/MINOR: sink/log: properly deinit srv in sink_new_from_logsrv()
EXAMPLES: maintain haproxy 2.8 retrocompatibility for lua mailers script
BUG/MINOR: hlua_fcn/queue: use atomic load to fetch queue size
BUG/MINOR: hlua: hlua_yieldk ctx argument should support pointers
BUG/MEDIUM: hlua_fcn/queue: bad pop_wait sequencing
Christopher Faulet (11):
DOC: config: Fix fc_src description to state the source address is
returned
BUG/MINOR: sample: Fix wrong overflow detection in add/sub conveters
BUG/MINOR: http: Return the right reason for 302
BUG/MINOR: h1-htx: Return the right reason for 302 FCGI responses
BUG/MINOR: server: Don't warn on server resolution failure with init-addr
none
BUG/MEDIUM: listener: Acquire proxy's lock in relax_listener() if
necessary
BUG/MEDIUM: h3: Properly report a C-L header was found to the HTX
start-line
BUG/MEDIUM: h3: Be sure to handle fin bit on the last DATA frame
BUG/MEDIUM: bwlim: Reset analyse expiration date when then channel
analyse ends
BUG/MINOR: http-client: Don't forget to commit changes on HTX message
BUG/MAJOR: http-ana: Get a fresh trash buffer for each header value
replacement
Dragan Dosen (1):
BUG/MINOR: chunk: fix chunk_appendf() to not write a zero if buffer is
full
Emeric Brun (6):
BUG/MEDIUM: quic: token IV was not computed using a strong secret
BUG/MINOR: quic: retry token remove one useless intermediate expand
BUG/MEDIUM: quic: missing check of dcid for init pkt including a token
BUG/MEDIUM: quic: timestamp shared in token was using internal time clock
CLEANUP: quic: remove useless parameter 'key' from quic_packet_encrypt
BUILD: quic: fix warning during compilation using gcc-6.5
Frédéric Lécaille (3):
BUG/MINOR: quic: Missing parentheses around PTO probe variable.
MINOR: quic: Make ->set_encryption_secrets() be callable two times
MINOR: quic: Useless call to SSL_CTX_set_quic_method()
Ilya Shipitsin (2):
CI: add naming convention documentation
CI: explicitely highlight VTest result section if there's something
Marcos de Oliveira (2):
BUG/MINOR: server-state: Ignore empty files
BUG/MINOR: server-state: Avoid warning on 'file not found'
Remi Tricot-Le Breton (4):
DOC: ssl: Fix typo in 'ocsp-update' option
DOC: ssl: Add ocsp-update troubleshooting clues and emphasize on crt-list
only aspect
BUG/MINOR: cache: A 'max-age=0' cache-control directive can be overriden
by a s-maxage
BUG/MINOR: ssl: OCSP callback only registered for first SSL_CTX
Thierry Fournier (1):
BUG/MINOR: config: Remove final '\n' in error messages
William Lallemand (1):
DOC: configuration: describe Td in Timing events
Willy Tarreau (17):
MINOR: cpuset: add cpu_map_configured() to know if a cpu-map was found
BUG/MINOR: config: do not detect NUMA topology when cpu-map is configured
BUG/MINOR: cpuset: remove the bogus "proc" from the cpu_map struct
BUG/MINOR: init: set process' affinity even in foreground
REORG: http: move has_forbidden_char() from h2.c to http.h
BUG/MAJOR: h3: reject header values containing invalid chars
BUG/MAJOR: http: reject any empty content-length header value
MINOR: ist: add new function ist_find_range() to find a character range
MINOR: http: add new function http_path_has_forbidden_char()
MINOR: h2: pass accept-invalid-http-request down the request parser
REGTESTS: http-rules: add accept-invalid-http-request for normalize-uri
tests
BUG/MINOR: h1: do not accept '#' as part of the URI component
BUG/MINOR: h2: reject more chars from the :path pseudo header
BUG/MINOR: h3: reject more chars from the :path pseudo header
REGTESTS: http-rules: verify that we block '#' by default for
normalize-uri
DOC: clarify the handling of URL fragments in requests
BUG/MINOR: http: skip leading zeroes in content-length values
firexinghe (1):
BUG/MINOR: hlua: add check for lua_newstate
---