Hi,

HAProxy 2.7.10 was released on 2023/08/09. It added 84 new commits
after version 2.7.9.

As mentioned in the 2.8.2 announce, some moderate security issues were
addressed.

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.

  - 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.

  - quic: assorted minor-level issues that had already been addressed in
    2.8.1.

  - 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).

  - the "namespace" keyword in default-servers was parsed but ignored

  - the duplicate stick-table name check did not work for tables declared
    inside peers sections.

  - mworker: automatically adjust the master's maxconn to support the
    sockets used to connect to workers.

  - http compression will now flush partial messages to allow low-latency
    interactive communications to work (e.g. CouchDB's heartbeats).


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.7/src/
   Git repository   : https://git.haproxy.org/git/haproxy-2.7.git/
   Git Web browsing : https://git.haproxy.org/?p=haproxy-2.7.git
   Changelog        : https://www.haproxy.org/download/2.7/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 (17):
      BUG/MINOR: server: inherit from netns in srv_settings_cpy()
      BUG/MINOR: namespace: missing free in netns_sig_stop()
      BUG/MINOR: tcp_sample: bc_{dst,src} return IP not INT
      BUG/MEDIUM: sink: invalid server list in sink_new_from_logsrv()
      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: sink/log: properly deinit srv in sink_new_from_logsrv()
      BUG/MINOR: hlua: hlua_yieldk ctx argument should support pointers

Christopher Faulet (10):
      REGTESTS: h1_host_normalization : Add a barrier to not mix up log messages
      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/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/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 (7):
      BUG/MEDIUM: quic: error checking buffer large enought to receive the 
retry tag
      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 (17):
      BUG/MINOR: quic: Wrong encryption level flags checking
      BUG/MINOR: quic: Address inversion in "show quic full"
      BUG/MINOR: quic: Missing initialization (packet number space probing)
      BUG/MINOR: quic: Possible crash in quic_conn_prx_cntrs_update()
      BUG/MINOR: quic: Possible endless loop in quic_lstnr_dghdlr()
      BUG/MINOR: quic: ticks comparison without ticks API use
      BUG/MINOR: quic: Prevent deadlock with CID tree lock
      BUG/MINOR: quic: Missing random bits in Retry packet header
      BUG/MINOR: quic: Wrong Retry paquet version field endianess
      BUG/MINOR: quic: Wrong endianess for version field in Retry token
      MINOR: quic: Move QUIC encryption level structure definition
      MINOR: quic: Move packet number space related functions
      MINOR: quic: Reduce the maximum length of TLS secrets
      CLEANUP: quic: Remove server specific about Initial packet number space
      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

Patrick Hemmer (1):
      BUG/MINOR: config: fix stick table duplicate name check

Remi Tricot-Le Breton (1):
      BUG/MINOR: cache: A 'max-age=0' cache-control directive can be overriden 
by a s-maxage

Thierry Fournier (1):
      BUG/MINOR: config: Remove final '\n' in error messages

Tim Duesterhus (1):
      DOC: Add tune.h2.max-frame-size option to table of contents

William Lallemand (3):
      BUG/MEDIUM: mworker: increase maxsock with each new worker
      BUG/MINOR: mworker: leak of a socketpair during startup failure
      DOC: configuration: describe Td in Timing events

Willy Tarreau (19):
      IMPORT: slz: implement a synchronous flush() operation
      MINOR: compression/slz: add support for a pure flush of pending bytes
      BUILD: debug: avoid a build warning related to epoll_wait() in debug code
      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
      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

---

Reply via email to