]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: h3: ensure the ":method" pseudo header is totally valid
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 28 Jun 2024 08:43:19 +0000 (10:43 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 28 Jun 2024 12:36:30 +0000 (14:36 +0200)
Ensure pseudo-header method is only constitued of valid characters
according to RFC 9110. If an invalid value is found, the request is
rejected and stream is resetted.

Previously only characters forbidden in headers were rejected (NUL/CR/LF),
but this is insufficient for :method, where some other forbidden chars
might be used to trick a non-compliant backend server into seeing a
different path from the one seen by haproxy. Note that header injection
is not possible though.

This must be backported up to 2.6.

Many thanks to Yuki Mogi of FFRI Security Inc for the detailed report
that allowed to quicky spot, confirm and fix the problem.

include/haproxy/http.h
src/h3.c

index e28f3cc902ded45c845d7aa79ccb8ecc7108ad29..f7f804d7dd586303e1af2ded803d7bfa38e4ef2a 100644 (file)
@@ -197,6 +197,21 @@ static inline int http_header_has_forbidden_char(const struct ist ist, const cha
        return 0;
 }
 
+/* Check that method only contains token as required.
+ * See RFC 9110 9. Methods
+ */
+static inline int http_method_has_forbidden_char(const struct ist ist)
+{
+       const char *start = istptr(ist);
+
+       do {
+               if (!HTTP_IS_TOKEN(*start))
+                       return 1;
+               start++;
+       } while (start < istend(ist));
+       return 0;
+}
+
 /* Looks into <ist> for forbidden characters for :path values (0x00..0x1F,
  * 0x20, 0x23), starting at pointer <start> which must be within <ist>.
  * Returns non-zero if such a character is found, 0 otherwise. When run on
index 2aa4fa78e3a18799944a19db1a8843d06a11f16a..fac9846d950dbc02f68ac8908b736be06169448b 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -630,6 +630,15 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                                len = -1;
                                goto out;
                        }
+
+                       if (!istlen(list[hdr_idx].v) || http_method_has_forbidden_char(list[hdr_idx].v)) {
+                               TRACE_ERROR("invalid method pseudo-header", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
+                               h3s->err = H3_ERR_MESSAGE_ERROR;
+                               qcc_report_glitch(h3c->qcc, 1);
+                               len = -1;
+                               goto out;
+                       }
+
                        meth = list[hdr_idx].v;
                }
                else if (isteq(list[hdr_idx].n, ist(":path"))) {