diff options
Diffstat (limited to 'debian')
-rw-r--r-- | debian/changelog | 18 | ||||
-rw-r--r-- | debian/control | 3 | ||||
-rw-r--r-- | debian/patches/0008-CVE-2024-38474-regression-mod_rewrite-Better-questio.patch | 241 | ||||
-rw-r--r-- | debian/patches/0009-CVE-2024-38474-regression-mod_rewrite-Improve-safe-q.patch | 75 | ||||
-rw-r--r-- | debian/patches/0010-VE-2024-39884-Regression-Remove-support-for-Request-.patch | 160 | ||||
-rw-r--r-- | debian/patches/series | 11 |
6 files changed, 499 insertions, 9 deletions
diff --git a/debian/changelog b/debian/changelog index ad89c9c..cfeef9d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,21 @@ +apache2 (2.4.62-3) unstable; urgency=medium + + * Fix debian/changelog + + -- Bastien Roucariès <rouca@debian.org> Fri, 04 Oct 2024 13:35:02 +0000 + +apache2 (2.4.62-2) unstable; urgency=medium + + * Add myself as maintainer with yadd agreement. + * Fix CVE-2024-38474 regression: + Better question mark tracking to avoid UnsafeAllow3F + (Closes: #1079172) + * Fix CVE-2024-39884 regression: + Trust strings from configuration in mod_proxy + (Closes: #1079206) + + -- Bastien Roucariès <rouca@debian.org> Sun, 29 Sep 2024 18:47:03 +0000 + apache2 (2.4.62-1~progress7.99u1) graograman-backports; urgency=medium * Uploading to graograman-backports, remaining changes: diff --git a/debian/control b/debian/control index 52cc370..27e50d7 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,8 @@ XSBC-Original-Maintainer: Debian Apache Maintainers <debian-apache@lists.debian. XSBC-Original-Uploaders: Stefan Fritsch <sf@debian.org>, Arno Töll <arno@debian.org>, Ondřej Surý <ondrej@debian.org>, - Yadd <yadd@debian.org> + Yadd <yadd@debian.org>, + Bastien Roucaries <rouca@debian.org> Bugs: mailto:maintainers@lists.progress-linux.org Section: httpd Priority: optional diff --git a/debian/patches/0008-CVE-2024-38474-regression-mod_rewrite-Better-questio.patch b/debian/patches/0008-CVE-2024-38474-regression-mod_rewrite-Better-questio.patch new file mode 100644 index 0000000..40f1a8e --- /dev/null +++ b/debian/patches/0008-CVE-2024-38474-regression-mod_rewrite-Better-questio.patch @@ -0,0 +1,241 @@ +From: Yann Ylavic <ylavic@apache.org> +Date: Sat, 27 Jul 2024 13:35:53 +0000 +Subject: CVE-2024-38474 regression mod_rewrite: Better question mark tracking + to avoid UnsafeAllow3F. PR 69197. + +Track in do_expand() whether a '?' in the uri-path comes from a literal in +the substitution string or from an expansion (variable, lookup, ...). +In the former case it's safe to assume that it's the query-string separator +but for the other case it's not (could be a decoded %3f from r->uri). + +This allows to avoid [UnsafeAllow3F] for most cases. + +Merges r1919325 from trunk +Reviewed by: ylavic, covener, jorton +Github: closes #462 + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1919545 13f79535-47bb-0310-9956-ffa450edef68 +origin: https://github.com/apache/httpd/commit/a0a68b99d131741c1867cff321424892838fc4b3 +bug: https://bz.apache.org/bugzilla/show_bug.cgi?id=69197 +bug-github: https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/462 +--- + modules/mappers/mod_rewrite.c | 107 +++++++++++++++++++++++++++++++++++------- + 1 file changed, 89 insertions(+), 18 deletions(-) + +diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c +index f1c22e3..53fb1e9 100644 +--- a/modules/mappers/mod_rewrite.c ++++ b/modules/mappers/mod_rewrite.c +@@ -2376,9 +2376,16 @@ static APR_INLINE char *find_char_in_curlies(char *s, int c) + * of an earlier expansion to include expansion specifiers that + * are interpreted by a later expansion, producing results that + * were not intended by the administrator. ++ * ++ * unsafe_qmark if not NULL will be set to 1 or 0 if a question mark ++ * is found respectively in a literal or in a lookup/expansion (whether ++ * it's the first or last qmark depends on [QSL]). Should be initialized ++ * to -1 and remains so if no qmark is found. + */ +-static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) ++static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry, ++ int *unsafe_qmark) + { ++#define EXPAND_SPECIALS "\\$%" + result_list *result, *current; + result_list sresult[SMALL_EXPANSION]; + unsigned spc = 0; +@@ -2386,8 +2393,29 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + char *p, *c; + apr_pool_t *pool = ctx->r->pool; + +- span = strcspn(input, "\\$%"); + inputlen = strlen(input); ++ if (!unsafe_qmark) { ++ span = strcspn(input, EXPAND_SPECIALS); ++ } ++ else { ++ span = strcspn(input, EXPAND_SPECIALS "?"); ++ if (input[span] == '?') { ++ /* this qmark is not from an expansion thus safe */ ++ *unsafe_qmark = 0; ++ ++ /* keep tracking only if interested in the last qmark */ ++ if (entry && (entry->flags & RULEFLAG_QSLAST)) { ++ do { ++ span++; ++ span += strcspn(input + span, EXPAND_SPECIALS "?"); ++ } while (input[span] == '?'); ++ } ++ else { ++ unsafe_qmark = NULL; ++ span += strcspn(input + span, EXPAND_SPECIALS); ++ } ++ } ++ } + + /* fast exit */ + if (inputlen == span) { +@@ -2405,6 +2433,8 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + + /* loop for specials */ + do { ++ int expanded = 0; ++ + /* prepare next entry */ + if (current->len) { + current->next = (spc < SMALL_EXPANSION) +@@ -2450,6 +2480,8 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + current->len = span; + current->string = p; + outlen += span; ++ ++ expanded = 1; + p = endp + 1; + } + +@@ -2489,19 +2521,18 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + } + + /* reuse of key variable as result */ +- key = lookup_map(ctx->r, map, do_expand(key, ctx, entry)); +- ++ key = lookup_map(ctx->r, map, do_expand(key, ctx, entry, NULL)); + if (!key && dflt && *dflt) { +- key = do_expand(dflt, ctx, entry); ++ key = do_expand(dflt, ctx, entry, NULL); + } +- +- if (key) { ++ if (key && *key) { + span = strlen(key); + current->len = span; + current->string = key; + outlen += span; + } + ++ expanded = 1; + p = endp + 1; + } + } +@@ -2531,8 +2562,9 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + current->len = span; + current->string = bri->source + bri->regmatch[n].rm_so; + } +- + outlen += span; ++ ++ expanded = 1; + } + + p += 2; +@@ -2545,8 +2577,41 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry) + ++outlen; + } + ++ if (unsafe_qmark && expanded && current->len ++ && memchr(current->string, '?', current->len)) { ++ /* this qmark is from an expansion thus unsafe */ ++ *unsafe_qmark = 1; ++ ++ /* keep tracking only if interested in the last qmark */ ++ if (!entry || !(entry->flags & RULEFLAG_QSLAST)) { ++ unsafe_qmark = NULL; ++ } ++ } ++ + /* check the remainder */ +- if (*p && (span = strcspn(p, "\\$%")) > 0) { ++ if (!unsafe_qmark) { ++ span = strcspn(p, EXPAND_SPECIALS); ++ } ++ else { ++ span = strcspn(p, EXPAND_SPECIALS "?"); ++ if (p[span] == '?') { ++ /* this qmark is not from an expansion thus safe */ ++ *unsafe_qmark = 0; ++ ++ /* keep tracking only if interested in the last qmark */ ++ if (entry && (entry->flags & RULEFLAG_QSLAST)) { ++ do { ++ span++; ++ span += strcspn(p + span, EXPAND_SPECIALS "?"); ++ } while (p[span] == '?'); ++ } ++ else { ++ unsafe_qmark = NULL; ++ span += strcspn(p + span, EXPAND_SPECIALS); ++ } ++ } ++ } ++ if (span > 0) { + if (current->len) { + current->next = (spc < SMALL_EXPANSION) + ? &(sresult[spc++]) +@@ -2591,7 +2656,7 @@ static void do_expand_env(data_item *env, rewrite_ctx *ctx) + char *name, *val; + + while (env) { +- name = do_expand(env->data, ctx, NULL); ++ name = do_expand(env->data, ctx, NULL, NULL); + if (*name == '!') { + name++; + apr_table_unset(ctx->r->subprocess_env, name); +@@ -2725,7 +2790,7 @@ static void add_cookie(request_rec *r, char *s) + static void do_expand_cookie(data_item *cookie, rewrite_ctx *ctx) + { + while (cookie) { +- add_cookie(ctx->r, do_expand(cookie->data, ctx, NULL)); ++ add_cookie(ctx->r, do_expand(cookie->data, ctx, NULL, NULL)); + cookie = cookie->next; + } + +@@ -4014,7 +4079,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx) + int basis; + + if (p->ptype != CONDPAT_AP_EXPR) +- input = do_expand(p->input, ctx, NULL); ++ input = do_expand(p->input, ctx, NULL, NULL); + + switch (p->ptype) { + case CONDPAT_FILE_EXISTS: +@@ -4178,7 +4243,7 @@ static APR_INLINE void force_type_handler(rewriterule_entry *p, + char *expanded; + + if (p->forced_mimetype) { +- expanded = do_expand(p->forced_mimetype, ctx, p); ++ expanded = do_expand(p->forced_mimetype, ctx, p, NULL); + + if (*expanded) { + ap_str_tolower(expanded); +@@ -4192,7 +4257,7 @@ static APR_INLINE void force_type_handler(rewriterule_entry *p, + } + + if (p->forced_handler) { +- expanded = do_expand(p->forced_handler, ctx, p); ++ expanded = do_expand(p->forced_handler, ctx, p, NULL); + + if (*expanded) { + ap_str_tolower(expanded); +@@ -4329,12 +4394,18 @@ static rule_return_type apply_rewrite_rule(rewriterule_entry *p, + + /* expand the result */ + if (!(p->flags & RULEFLAG_NOSUB)) { +- newuri = do_expand(p->output, ctx, p); ++ int unsafe_qmark = -1; ++ ++ if (p->flags & RULEFLAG_UNSAFE_ALLOW3F) { ++ newuri = do_expand(p->output, ctx, p, NULL); ++ } ++ else { ++ newuri = do_expand(p->output, ctx, p, &unsafe_qmark); ++ } + rewritelog((r, 2, ctx->perdir, "rewrite '%s' -> '%s'", ctx->uri, + newuri)); +- if (!(p->flags & RULEFLAG_UNSAFE_ALLOW3F) && +- ap_strcasestr(r->unparsed_uri, "%3f") && +- ap_strchr_c(newuri, '?')) { ++ ++ if (unsafe_qmark > 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10508) + "Unsafe URL with %%3f URL rewritten without " + "UnsafeAllow3F"); diff --git a/debian/patches/0009-CVE-2024-38474-regression-mod_rewrite-Improve-safe-q.patch b/debian/patches/0009-CVE-2024-38474-regression-mod_rewrite-Improve-safe-q.patch new file mode 100644 index 0000000..4c5ff8c --- /dev/null +++ b/debian/patches/0009-CVE-2024-38474-regression-mod_rewrite-Improve-safe-q.patch @@ -0,0 +1,75 @@ +From: Eric Covener <covener@apache.org> +Date: Fri, 27 Sep 2024 13:11:05 +0000 +Subject: CVE-2024-38474 regression mod_rewrite: Improve safe question mark + detection + + Trunk version of patch: + https://svn.apache.org/r1920566 + Backport version for 2.4.x of patch: + Trunk version of patch works + svn merge -c 1920566 ^/httpd/httpd/trunk . + +1: rpluem, covener, jorton + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1920982 13f79535-47bb-0310-9956-ffa450edef68 +origin: https://github.com/apache/httpd/commit/c91445b7f905587aa86ad552f4a1a3f29345e695 +--- + modules/mappers/mod_rewrite.c | 32 ++++++++++++++------------------ + 1 file changed, 14 insertions(+), 18 deletions(-) + +diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c +index 53fb1e9..c8c5dbd 100644 +--- a/modules/mappers/mod_rewrite.c ++++ b/modules/mappers/mod_rewrite.c +@@ -2404,21 +2404,19 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry, + *unsafe_qmark = 0; + + /* keep tracking only if interested in the last qmark */ +- if (entry && (entry->flags & RULEFLAG_QSLAST)) { +- do { +- span++; +- span += strcspn(input + span, EXPAND_SPECIALS "?"); +- } while (input[span] == '?'); +- } +- else { ++ if (!entry || !(entry->flags & RULEFLAG_QSLAST)) { + unsafe_qmark = NULL; +- span += strcspn(input + span, EXPAND_SPECIALS); + } ++ ++ /* find the next real special char, any (last) qmark up to ++ * there is safe too ++ */ ++ span += strcspn(input + span, EXPAND_SPECIALS); + } + } + +- /* fast exit */ +- if (inputlen == span) { ++ /* fast path (no specials) */ ++ if (span >= inputlen) { + return apr_pstrmemdup(pool, input, inputlen); + } + +@@ -2599,16 +2597,14 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry, + *unsafe_qmark = 0; + + /* keep tracking only if interested in the last qmark */ +- if (entry && (entry->flags & RULEFLAG_QSLAST)) { +- do { +- span++; +- span += strcspn(p + span, EXPAND_SPECIALS "?"); +- } while (p[span] == '?'); +- } +- else { ++ if (!entry || !(entry->flags & RULEFLAG_QSLAST)) { + unsafe_qmark = NULL; +- span += strcspn(p + span, EXPAND_SPECIALS); + } ++ ++ /* find the next real special char, any (last) qmark up to ++ * there is safe too ++ */ ++ span += strcspn(p + span, EXPAND_SPECIALS); + } + } + if (span > 0) { diff --git a/debian/patches/0010-VE-2024-39884-Regression-Remove-support-for-Request-.patch b/debian/patches/0010-VE-2024-39884-Regression-Remove-support-for-Request-.patch new file mode 100644 index 0000000..446bb1a --- /dev/null +++ b/debian/patches/0010-VE-2024-39884-Regression-Remove-support-for-Request-.patch @@ -0,0 +1,160 @@ +From: Eric Covener <covener@apache.org> +Date: Fri, 27 Sep 2024 13:10:34 +0000 +Subject: VE-2024-39884 Regression Remove support for Request-Range header + sent by Navigator 2-3 and MSIE 3 + +Strings are from configuration and thus trusted + +Submitted by: sf, rpluem +Reviewed by: rpluem, covener, jorton + +Github: closes #475 +bug-debian: https://bugs.debian.org/1079206 +bug: https://github.com/apache/httpd/pull/475 +origin: https://github.com/apache/httpd/commit/5f82765bc640ddb6a13a681464856bf8f8a5cb10 +--- + modules/filters/mod_ext_filter.c | 2 +- + modules/generators/mod_autoindex.c | 6 +++--- + modules/http/byterange_filter.c | 43 ++++++-------------------------------- + modules/http/http_request.c | 2 +- + modules/proxy/mod_proxy_ftp.c | 4 ++-- + 5 files changed, 13 insertions(+), 44 deletions(-) + +diff --git a/modules/filters/mod_ext_filter.c b/modules/filters/mod_ext_filter.c +index 7afd8dd..6a7c9e4 100644 +--- a/modules/filters/mod_ext_filter.c ++++ b/modules/filters/mod_ext_filter.c +@@ -610,7 +610,7 @@ static apr_status_t init_filter_instance(ap_filter_t *f) + } + if (ctx->filter->outtype && + ctx->filter->outtype != OUTTYPE_UNCHANGED) { +- ap_set_content_type(f->r, ctx->filter->outtype); ++ ap_set_content_type_ex(f->r, ctx->filter->outtype, 1); + } + if (ctx->filter->preserves_content_length != 1) { + /* nasty, but needed to avoid confusing the browser +diff --git a/modules/generators/mod_autoindex.c b/modules/generators/mod_autoindex.c +index cb44603..6280430 100644 +--- a/modules/generators/mod_autoindex.c ++++ b/modules/generators/mod_autoindex.c +@@ -2052,11 +2052,11 @@ static int index_directory(request_rec *r, + #endif + } + if (*charset) { +- ap_set_content_type(r, apr_pstrcat(r->pool, ctype, ";charset=", +- charset, NULL)); ++ ap_set_content_type_ex(r, apr_pstrcat(r->pool, ctype, ";charset=", ++ charset, NULL), 1); + } + else { +- ap_set_content_type(r, ctype); ++ ap_set_content_type_ex(r, ctype, 1); + } + + if (autoindex_opts & TRACK_MODIFIED) { +diff --git a/modules/http/byterange_filter.c b/modules/http/byterange_filter.c +index 5ebe853..a1ffdd3 100644 +--- a/modules/http/byterange_filter.c ++++ b/modules/http/byterange_filter.c +@@ -100,21 +100,7 @@ static int ap_set_byterange(request_rec *r, apr_off_t clength, + return 0; + } + +- /* +- * Check for Range request-header (HTTP/1.1) or Request-Range for +- * backwards-compatibility with second-draft Luotonen/Franks +- * byte-ranges (e.g. Netscape Navigator 2-3). +- * +- * We support this form, with Request-Range, and (farther down) we +- * send multipart/x-byteranges instead of multipart/byteranges for +- * Request-Range based requests to work around a bug in Netscape +- * Navigator 2-3 and MSIE 3. +- */ +- +- if (!(range = apr_table_get(r->headers_in, "Range"))) { +- range = apr_table_get(r->headers_in, "Request-Range"); +- } +- ++ range = apr_table_get(r->headers_in, "Range"); + if (!range || strncasecmp(range, "bytes=", 6) || r->status != HTTP_OK) { + return 0; + } +@@ -126,10 +112,9 @@ static int ap_set_byterange(request_rec *r, apr_off_t clength, + + /* is content already a multiple range? */ + if ((ct = apr_table_get(r->headers_out, "Content-Type")) +- && (!strncasecmp(ct, "multipart/byteranges", 20) +- || !strncasecmp(ct, "multipart/x-byteranges", 22))) { ++ && strncasecmp(ct, "multipart/byteranges", 20) == 0) { + return 0; +- } ++ } + + /* + * Check the If-Range header for Etag or Date. +@@ -298,21 +283,6 @@ static int ap_set_byterange(request_rec *r, apr_off_t clength, + return num_ranges; + } + +-/* +- * Here we try to be compatible with clients that want multipart/x-byteranges +- * instead of multipart/byteranges (also see above), as per HTTP/1.1. We +- * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication +- * that the browser supports an older protocol. We also check User-Agent +- * for Microsoft Internet Explorer 3, which needs this as well. +- */ +-static int use_range_x(request_rec *r) +-{ +- const char *ua; +- return (apr_table_get(r->headers_in, "Request-Range") +- || ((ua = apr_table_get(r->headers_in, "User-Agent")) +- && ap_strstr_c(ua, "MSIE 3"))); +-} +- + #define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT + + static apr_status_t copy_brigade_range(apr_bucket_brigade *bb, +@@ -503,10 +473,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f, + /* Is ap_make_content_type required here? */ + const char *orig_ct = ap_make_content_type(r, r->content_type); + +- ap_set_content_type(r, apr_pstrcat(r->pool, "multipart", +- use_range_x(r) ? "/x-" : "/", +- "byteranges; boundary=", +- ap_multipart_boundary, NULL)); ++ ap_set_content_type_ex(r, apr_pstrcat(r->pool, ++ "multipart/byteranges; boundary=", ++ ap_multipart_boundary, NULL), 1); + + if (orig_ct) { + bound_head = apr_pstrcat(r->pool, +diff --git a/modules/http/http_request.c b/modules/http/http_request.c +index 7e9477b..46da143 100644 +--- a/modules/http/http_request.c ++++ b/modules/http/http_request.c +@@ -808,7 +808,7 @@ AP_DECLARE(void) ap_internal_redirect_handler(const char *new_uri, request_rec * + } + + if (r->handler) +- ap_set_content_type(new, r->content_type); ++ ap_set_content_type_ex(new, r->content_type, AP_REQUEST_IS_TRUSTED_CT(r)); + access_status = ap_process_request_internal(new); + if (access_status == OK) { + access_status = ap_invoke_handler(new); +diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c +index e0032e5..5175e45 100644 +--- a/modules/proxy/mod_proxy_ftp.c ++++ b/modules/proxy/mod_proxy_ftp.c +@@ -1878,10 +1878,10 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, + + /* set content-type */ + if (dirlisting) { +- ap_set_content_type(r, apr_pstrcat(p, "text/html;charset=", ++ ap_set_content_type_ex(r, apr_pstrcat(p, "text/html;charset=", + fdconf->ftp_directory_charset ? + fdconf->ftp_directory_charset : +- "ISO-8859-1", NULL)); ++ "ISO-8859-1", NULL), 1); + } + else { + if (xfer_type != 'A' && size != NULL) { diff --git a/debian/patches/series b/debian/patches/series index d2c00e2..603d1d9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -4,12 +4,7 @@ suexec-CVE-2007-1742.patch customize_apxs.patch build_suexec-custom.patch reproducible_builds.diff -#mod_proxy_ajp-add-secret-parameter.diff -#buffer-http-request-bodies-for-tlsv13.diff -#tlsv13-add-logno.diff fix-macro.patch -#pcre2.patch -#child_processes_fail_to_start.patch - -# This patch is applied manually -#suexec-custom.patch +0008-CVE-2024-38474-regression-mod_rewrite-Better-questio.patch +0009-CVE-2024-38474-regression-mod_rewrite-Improve-safe-q.patch +0010-VE-2024-39884-Regression-Remove-support-for-Request-.patch |