diff --git a/backport-001-CVE-2021-44224.patch b/backport-001-CVE-2021-44224.patch new file mode 100644 index 0000000000000000000000000000000000000000..a376c779730e382beda06e5af1f3f4134cc2fec7 --- /dev/null +++ b/backport-001-CVE-2021-44224.patch @@ -0,0 +1,258 @@ +From a962ba73047b5478d702c8ad09fd1a167e1d3736 Mon Sep 17 00:00:00 2001 +From: Yann Ylavic +Date: Tue, 14 Dec 2021 15:35:56 +0000 +Subject: [PATCH] Merge r1895914, r1895921 from trunk: + + *) http: Enforce that fully qualified uri-paths not to be forward-proxied + have an http(s) scheme, and that the ones to be forward proxied have a + hostname, per HTTP specifications. + trunk patch: http://svn.apache.org/r1895914 + http://svn.apache.org/r1895921 + 2.4.x patch: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/286.patch + backport PR: https://github.com/apache/httpd/pull/286 + +1: ylavic, minfrin, gbechis + + +mod_proxy: Detect unix: scheme syntax errors at load time. + +* modules/proxy/mod_proxy.c(add_pass, add_member, set_proxy_param, + proxysection): + Check return value of ap_proxy_de_socketfy(). + +* modules/proxy/proxy_util.c(ap_proxy_get_worker): + Check return value of ap_proxy_de_socketfy(). + + + +http: Enforce that fully qualified uri-paths not to be forward-proxied + have an http(s) scheme, and that the ones to be forward proxied have a + hostname, per HTTP specifications. + +The early checks avoid failing the request later on and thus save cycles +for those invalid cases. + + +Submitted by: ylavic +Reviewed by: ylavic, minfrin, gbechis +Closes #286 + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1895955 13f79535-47bb-0310-9956-ffa450edef68 +--- + include/http_protocol.h | 7 ++++++ + modules/http/http_request.c | 2 +- + modules/http2/h2_request.c | 2 +- + modules/proxy/mod_proxy.c | 44 ++++++++++++++++++++++++++----------- + modules/proxy/proxy_util.c | 3 +++ + server/protocol.c | 23 ++++++++++++++++++- + 6 files changed, 71 insertions(+), 17 deletions(-) + +diff --git a/include/http_protocol.h b/include/http_protocol.h +index 9ccac893fcb..20bd2022266 100644 +--- a/include/http_protocol.h ++++ b/include/http_protocol.h +@@ -96,6 +96,13 @@ AP_DECLARE(void) ap_get_mime_headers(request_rec *r); + AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, + apr_bucket_brigade *bb); + ++/** ++ * Run post_read_request hook and validate. ++ * @param r The current request ++ * @return OK or HTTP_... ++ */ ++AP_DECLARE(int) ap_post_read_request(request_rec *r); ++ + /* Finish up stuff after a request */ + + /** +diff --git a/modules/http/http_request.c b/modules/http/http_request.c +index c9ae5af2864..d59cfe25999 100644 +--- a/modules/http/http_request.c ++++ b/modules/http/http_request.c +@@ -680,7 +680,7 @@ static request_rec *internal_internal_redirect(const char *new_uri, + * to do their thing on internal redirects as well. Perhaps this is a + * misnamed function. + */ +- if ((access_status = ap_run_post_read_request(new))) { ++ if ((access_status = ap_post_read_request(new))) { + ap_die(access_status, new); + return NULL; + } +diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c +index 7c4fb95ea48..9ff6feb675f 100644 +--- a/modules/http2/h2_request.c ++++ b/modules/http2/h2_request.c +@@ -370,7 +370,7 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c) + NULL, r, r->connection); + + if (access_status != HTTP_OK +- || (access_status = ap_run_post_read_request(r))) { ++ || (access_status = ap_post_read_request(r))) { + /* Request check post hooks failed. An example of this would be a + * request for a vhost where h2 is disabled --> 421. + */ +diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c +index 3fb84c85935..85d7ce2e6c1 100644 +--- a/modules/proxy/mod_proxy.c ++++ b/modules/proxy/mod_proxy.c +@@ -775,13 +775,13 @@ static int proxy_detect(request_rec *r) + + /* Ick... msvc (perhaps others) promotes ternary short results to int */ + +- if (conf->req && r->parsed_uri.scheme) { ++ if (conf->req && r->parsed_uri.scheme && r->parsed_uri.hostname) { + /* but it might be something vhosted */ +- if (!(r->parsed_uri.hostname +- && !strcasecmp(r->parsed_uri.scheme, ap_http_scheme(r)) +- && ap_matches_request_vhost(r, r->parsed_uri.hostname, +- (apr_port_t)(r->parsed_uri.port_str ? r->parsed_uri.port +- : ap_default_port(r))))) { ++ if (ap_cstr_casecmp(r->parsed_uri.scheme, ap_http_scheme(r)) != 0 ++ || !ap_matches_request_vhost(r, r->parsed_uri.hostname, ++ (apr_port_t)(r->parsed_uri.port_str ++ ? r->parsed_uri.port ++ : ap_default_port(r)))) { + r->proxyreq = PROXYREQ_PROXY; + r->uri = r->unparsed_uri; + r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL); +@@ -2007,6 +2007,7 @@ static const char * + struct proxy_alias *new; + char *f = cmd->path; + char *r = NULL; ++ const char *real; + char *word; + apr_table_t *params = apr_table_make(cmd->pool, 5); + const apr_array_header_t *arr; +@@ -2093,6 +2094,10 @@ static const char * + if (r == NULL) { + return "ProxyPass|ProxyPassMatch needs a path when not defined in a location"; + } ++ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, r))) { ++ return "ProxyPass|ProxyPassMatch uses an invalid \"unix:\" URL"; ++ } ++ + + /* if per directory, save away the single alias */ + if (cmd->path) { +@@ -2109,7 +2114,7 @@ static const char * + } + + new->fake = apr_pstrdup(cmd->pool, f); +- new->real = apr_pstrdup(cmd->pool, ap_proxy_de_socketfy(cmd->pool, r)); ++ new->real = apr_pstrdup(cmd->pool, real); + new->flags = flags; + if (use_regex) { + new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED); +@@ -2635,6 +2640,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) + proxy_worker *worker; + char *path = cmd->path; + char *name = NULL; ++ const char *real; + char *word; + apr_table_t *params = apr_table_make(cmd->pool, 5); + const apr_array_header_t *arr; +@@ -2675,6 +2681,9 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) + return "BalancerMember must define balancer name when outside section"; + if (!name) + return "BalancerMember must define remote proxy server"; ++ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, name))) { ++ return "BalancerMember uses an invalid \"unix:\" URL"; ++ } + + ap_str_tolower(path); /* lowercase scheme://hostname */ + +@@ -2687,7 +2696,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) + } + + /* Try to find existing worker */ +- worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, ap_proxy_de_socketfy(cmd->temp_pool, name)); ++ worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, real); + if (!worker) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147) + "Defining worker '%s' for balancer '%s'", +@@ -2785,7 +2793,13 @@ static const char * + } + } + else { ++ const char *real; ++ ++ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, name))) { ++ return "ProxySet uses an invalid \"unix:\" URL"; ++ } ++ +- worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, ap_proxy_de_socketfy(cmd->temp_pool, name)); ++ worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, real); + if (!worker) { + if (in_proxy_section) { + err = ap_proxy_define_worker(cmd->pool, &worker, NULL, +@@ -2930,8 +2943,14 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) + } + } + else { ++ const char *real; ++ ++ if (!(real = ap_proxy_de_socketfy(cmd->temp_pool, conf->p))) { ++ return " uses an invalid \"unix:\" URL"; ++ } ++ + worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf, +- ap_proxy_de_socketfy(cmd->temp_pool, (char*)conf->p)); ++ real); + if (!worker) { + err = ap_proxy_define_worker(cmd->pool, &worker, NULL, + sconf, conf->p, 0); +diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c +index a3cf5460487..b4f6dcfadc6 100644 +--- a/modules/proxy/proxy_util.c ++++ b/modules/proxy/proxy_util.c +@@ -1742,6 +1742,9 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, + } + + url = ap_proxy_de_socketfy(p, url); ++ if (!url) { ++ return NULL; ++ } + + c = ap_strchr_c(url, ':'); + if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') { +diff --git a/server/protocol.c b/server/protocol.c +index 3d74c5b3058..2214f72b5a4 100644 +--- a/server/protocol.c ++++ b/server/protocol.c +@@ -1548,7 +1548,7 @@ request_rec *ap_read_request(conn_rec *conn) + NULL, r, r->connection); + + if (access_status != HTTP_OK +- || (access_status = ap_run_post_read_request(r))) { ++ || (access_status = ap_post_read_request(r))) { + ap_die(access_status, r); + ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); + ap_run_log_transaction(r); +@@ -1603,6 +1603,27 @@ request_rec *ap_read_request(conn_rec *conn) + return r; + } + ++AP_DECLARE(int) ap_post_read_request(request_rec *r) ++{ ++ int status; ++ ++ if ((status = ap_run_post_read_request(r))) { ++ return status; ++ } ++ ++ /* Enforce http(s) only scheme for non-forward-proxy requests */ ++ if (!r->proxyreq ++ && r->parsed_uri.scheme ++ && (ap_cstr_casecmpn(r->parsed_uri.scheme, "http", 4) != 0 ++ || (r->parsed_uri.scheme[4] != '\0' ++ && (apr_tolower(r->parsed_uri.scheme[4]) != 's' ++ || r->parsed_uri.scheme[5] != '\0')))) { ++ return HTTP_BAD_REQUEST; ++ } ++ ++ return OK; ++} ++ + /* if a request with a body creates a subrequest, remove original request's + * input headers which pertain to the body which has already been read. + * out-of-line helper function for ap_set_sub_req_protocol. diff --git a/backport-002-CVE-2021-44224.patch b/backport-002-CVE-2021-44224.patch new file mode 100644 index 0000000000000000000000000000000000000000..5c0180df318236472bef2e74accb4ea87613058e --- /dev/null +++ b/backport-002-CVE-2021-44224.patch @@ -0,0 +1,103 @@ +From a0521d289ae14e4ac004811dc1ef91b3e118a2f6 Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Thu, 16 Dec 2021 11:23:49 +0000 +Subject: [PATCH] Merge of r1895981,r1895986 from trunk: + + *) mod_proxy: Don't prevent forwarding URIs w/ no hostname. + (fix for r1895955 already in 2.4.x) + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1896044 13f79535-47bb-0310-9956-ffa450edef68 +--- + modules/proxy/mod_proxy.c | 5 +++-- + modules/proxy/mod_proxy.h | 1 + + modules/proxy/proxy_util.c | 22 ++++++++++++---------- + 3 files changed, 16 insertions(+), 12 deletions(-) + +diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c +index 85d7ce2e6c1..f8a4db68892 100644 +--- a/modules/proxy/mod_proxy.c ++++ b/modules/proxy/mod_proxy.c +@@ -775,9 +775,10 @@ static int proxy_detect(request_rec *r) + + /* Ick... msvc (perhaps others) promotes ternary short results to int */ + +- if (conf->req && r->parsed_uri.scheme && r->parsed_uri.hostname) { ++ if (conf->req && r->parsed_uri.scheme) { + /* but it might be something vhosted */ +- if (ap_cstr_casecmp(r->parsed_uri.scheme, ap_http_scheme(r)) != 0 ++ if (!r->parsed_uri.hostname ++ || ap_cstr_casecmp(r->parsed_uri.scheme, ap_http_scheme(r)) != 0 + || !ap_matches_request_vhost(r, r->parsed_uri.hostname, + (apr_port_t)(r->parsed_uri.port_str + ? r->parsed_uri.port +diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h +index 35acc49a4a3..be5b3a85394 100644 +--- a/modules/proxy/mod_proxy.h ++++ b/modules/proxy/mod_proxy.h +@@ -750,6 +750,7 @@ PROXY_DECLARE(int) ap_proxy_worker_can_upgrade(apr_pool_t *p, + + PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p, + proxy_worker *worker); ++#define AP_PROXY_WORKER_NO_UDS (1u << 3) + + /** + * Get the worker from proxy configuration +diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c +index b4f6dcfadc6..8cb315d9103 100644 +--- a/modules/proxy/proxy_util.c ++++ b/modules/proxy/proxy_util.c +@@ -1741,9 +1741,11 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, + return NULL; + } + +- url = ap_proxy_de_socketfy(p, url); +- if (!url) { +- return NULL; ++ if (!(AP_PROXY_WORKER_NO_UDS)) { ++ url = ap_proxy_de_socketfy(p, url); ++ if (!url) { ++ return NULL; ++ } + } + + c = ap_strchr_c(url, ':'); +@@ -2326,22 +2328,21 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker, + + access_status = proxy_run_pre_request(worker, balancer, r, conf, url); + if (access_status == DECLINED && *balancer == NULL) { +- *worker = ap_proxy_get_worker(r->pool, NULL, conf, *url); ++ const int forward = (r->proxyreq == PROXYREQ_PROXY); ++ *worker = ap_proxy_get_worker(r->pool, NULL, conf, *url); + if (*worker) { + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, + "%s: found worker %s for %s", + (*worker)->s->scheme, (*worker)->s->name, *url); +- *balancer = NULL; +- if (!fix_uds_filename(r, url)) { ++ if (!forward && !fix_uds_filename(r, url)) { + return HTTP_INTERNAL_SERVER_ERROR; + } + access_status = OK; + } +- else if (r->proxyreq == PROXYREQ_PROXY) { ++ else if (forward) { + if (conf->forward) { + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, + "*: found forward proxy worker for %s", *url); +- *balancer = NULL; + *worker = conf->forward; + access_status = OK; + /* +@@ -2355,8 +2357,8 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker, + else if (r->proxyreq == PROXYREQ_REVERSE) { + if (conf->reverse) { + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, +- "*: using default reverse proxy worker for %s (no keepalive)", *url); +- *balancer = NULL; ++ "*: using default reverse proxy worker for %s " ++ "(no keepalive)", *url); + *worker = conf->reverse; + access_status = OK; + /* diff --git a/backport-CVE-2021-44790.patch b/backport-CVE-2021-44790.patch new file mode 100644 index 0000000000000000000000000000000000000000..44cd994947651c99e7469e2b35e58ee24ce87fa5 --- /dev/null +++ b/backport-CVE-2021-44790.patch @@ -0,0 +1,29 @@ +From 07b9768cef6a224d256358c404c6ed5622d8acce Mon Sep 17 00:00:00 2001 +From: Stefan Eissing +Date: Thu, 16 Dec 2021 11:15:47 +0000 +Subject: [PATCH] Merge r1895970 from trunk: + + *) mod_lua: Improve error handling + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1896039 13f79535-47bb-0310-9956-ffa450edef68 +--- + modules/lua/lua_request.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c +index 67ff432..493b2bb 100644 +--- a/modules/lua/lua_request.c ++++ b/modules/lua/lua_request.c +@@ -410,6 +410,7 @@ static int req_parsebody(lua_State *L) + if (end == NULL) break; + key = (char *) apr_pcalloc(r->pool, 256); + filename = (char *) apr_pcalloc(r->pool, 256); ++ if (end - crlf <= 8) break; + vlen = end - crlf - 8; + buffer = (char *) apr_pcalloc(r->pool, vlen+1); + memcpy(buffer, crlf + 4, vlen); +-- +1.8.3.1 + diff --git a/httpd.spec b/httpd.spec index fc60b7af0d5fae056dcc5f275f9fe780075e2413..29df5c9a77d0443115ff9f6383fe2e556eeaffce 100644 --- a/httpd.spec +++ b/httpd.spec @@ -8,7 +8,7 @@ Name: httpd Summary: Apache HTTP Server Version: 2.4.48 -Release: 3 +Release: 4 License: ASL 2.0 URL: https://httpd.apache.org/ Source0: https://archive.apache.org/dist/httpd/httpd-%{version}.tar.bz2 @@ -77,6 +77,9 @@ Patch24: backport-003-CVE-2021-40438.patch Patch25: backport-004-CVE-2021-40438.patch Patch26: backport-001-CVE-2021-39275.patch Patch27: backport-002-CVE-2021-39275.patch +Patch28: backport-CVE-2021-44790.patch +Patch29: backport-001-CVE-2021-44224.patch +Patch30: backport-002-CVE-2021-44224.patch BuildRequires: gcc autoconf pkgconfig findutils xmlto perl-interpreter perl-generators systemd-devel BuildRequires: zlib-devel libselinux-devel lua-devel brotli-devel @@ -509,6 +512,12 @@ exit $rv %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Sat Dec 25 2021 orange-snn - 2.4.48-4 +- Type:cves +- ID:NA +- SUG:restart +- DESC:fix CVE-2021-44790 CVE-2021-44224 + * Wed Sep 29 2021 gaihuiying - 2.4.48-3 - Type:cves - ID:CVE-2021-40438 CVE-2021-39275