78 lines
2.7 KiB
Diff
78 lines
2.7 KiB
Diff
From 87fefebfbe3df218103502046a0871b235a48087 Mon Sep 17 00:00:00 2001
|
|
From: Amaury Denoyelle <adenoyelle@haproxy.com>
|
|
Date: Fri, 28 Jun 2024 10:43:19 +0200
|
|
Subject: [PATCH] BUG/MEDIUM: h3: ensure the ":method" pseudo header is totally
|
|
valid
|
|
Origin: https://github.com/haproxy/haproxy/commit/87fefebfbe3df218103502046a0871b235a48087
|
|
|
|
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.
|
|
|
|
(cherry picked from commit 789d4abd7328f0a745d67698e89bbb888d4d9b2c)
|
|
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
|
|
(cherry picked from commit 47d13c68cf198467a94e85a1caa44484a1e2e75c)
|
|
[cf: adapted]
|
|
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
|
|
---
|
|
include/haproxy/http.h | 15 +++++++++++++++
|
|
src/h3.c | 8 ++++++++
|
|
2 files changed, 23 insertions(+)
|
|
|
|
diff --git a/include/haproxy/http.h b/include/haproxy/http.h
|
|
index 299264051d28e..a297fa59b444a 100644
|
|
--- a/include/haproxy/http.h
|
|
+++ b/include/haproxy/http.h
|
|
@@ -192,6 +192,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
|
|
diff --git a/src/h3.c b/src/h3.c
|
|
index 9e415b3b56303..4e21f6b92f535 100644
|
|
--- a/src/h3.c
|
|
+++ b/src/h3.c
|
|
@@ -625,6 +625,14 @@ 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_MESSAGE_ERROR;
|
|
+ len = -1;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
meth = list[hdr_idx].v;
|
|
}
|
|
else if (isteq(list[hdr_idx].n, ist(":path"))) {
|