From: Elan Ruusamäe Date: Tue, 11 Jul 2017 08:50:03 +0000 (+0300) Subject: apply_to_2.2.32 patches; fixes CVE-2017-3167 CVE-2017-3169 CVE-2017-7668 CVE-2017... X-Git-Tag: auto/ac/apache-2.2.32-2 X-Git-Url: http://git.pld-linux.org/?p=packages%2Fapache.git;a=commitdiff_plain;h=refs%2Ftags%2Fauto%2Fac%2Fapache-2.2.32-2 apply_to_2.2.32 patches; fixes CVE-2017-3167 CVE-2017-3169 CVE-2017-7668 CVE-2017-7679 --- diff --git a/CVE-2017-3167.patch b/CVE-2017-3167.patch new file mode 100644 index 0000000..b6d139d --- /dev/null +++ b/CVE-2017-3167.patch @@ -0,0 +1,163 @@ + + Merge https://svn.apache.org/r1796348 from trunk: + + *) SECURITY: CVE-2017-3167 (cve.mitre.org) + Use of the ap_get_basic_auth_pw() by third-party modules outside of the + authentication phase may lead to authentication requirements being + bypassed. + [Emmanuel Dreyfus , Jacob Champion, Eric Covener] + + + Submitted By: Emmanuel Dreyfus , Jacob Champion, Eric Covener + Reviewed By: covener, ylavic, wrowe + +diff --git include/ap_mmn.h include/ap_mmn.h +index ce330a5..fcbce6f 100644 +--- include/ap_mmn.h ++++ include/ap_mmn.h +@@ -167,6 +167,8 @@ + * and ap_scan_vchar_obstext() + * Replaced fold boolean with with multiple bit flags + * to ap_[r]getline() ++ * 20051115.43 (2.2.33) Add ap_get_basic_auth_components() and deprecate ++ * ap_get_basic_auth_pw() + */ + + #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */ +@@ -174,7 +176,7 @@ + #ifndef MODULE_MAGIC_NUMBER_MAJOR + #define MODULE_MAGIC_NUMBER_MAJOR 20051115 + #endif +-#define MODULE_MAGIC_NUMBER_MINOR 42 /* 0...n */ ++#define MODULE_MAGIC_NUMBER_MINOR 43 /* 0...n */ + + /** + * Determine if the server's current MODULE_MAGIC_NUMBER is at least a +diff --git include/http_protocol.h include/http_protocol.h +index 1fed3b5..3fed9b2 100644 +--- include/http_protocol.h ++++ include/http_protocol.h +@@ -486,7 +486,11 @@ AP_DECLARE(void) ap_note_basic_auth_failure(request_rec *r); + AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r); + + /** +- * Get the password from the request headers ++ * Get the password from the request headers. This function has multiple side ++ * effects due to its prior use in the old authentication framework. ++ * ap_get_basic_auth_components() should be preferred. ++ * ++ * @deprecated @see ap_get_basic_auth_components + * @param r The current request + * @param pw The password as set in the headers + * @return 0 (OK) if it set the 'pw' argument (and assured +@@ -499,6 +503,25 @@ AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r); + */ + AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw); + ++#define AP_GET_BASIC_AUTH_PW_NOTE "AP_GET_BASIC_AUTH_PW_NOTE" ++ ++/** ++ * Get the username and/or password from the request's Basic authentication ++ * headers. Unlike ap_get_basic_auth_pw(), calling this function has no side ++ * effects on the passed request_rec. ++ * ++ * @param r The current request ++ * @param username If not NULL, set to the username sent by the client ++ * @param password If not NULL, set to the password sent by the client ++ * @return APR_SUCCESS if the credentials were successfully parsed and returned; ++ * APR_EINVAL if there was no authentication header sent or if the ++ * client was not using the Basic authentication scheme. username and ++ * password are unchanged on failure. ++ */ ++AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r, ++ const char **username, ++ const char **password); ++ + /** + * parse_uri: break apart the uri + * @warning Side Effects: +diff --git server/protocol.c server/protocol.c +index bd75766..2705bba 100644 +--- server/protocol.c ++++ server/protocol.c +@@ -1594,6 +1594,7 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw) + + t = ap_pbase64decode(r->pool, auth_line); + r->user = ap_getword_nulls (r->pool, &t, ':'); ++ apr_table_setn(r->notes, AP_GET_BASIC_AUTH_PW_NOTE, "1"); + r->ap_auth_type = "Basic"; + + *pw = t; +@@ -1601,6 +1602,53 @@ AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw) + return OK; + } + ++AP_DECLARE(apr_status_t) ap_get_basic_auth_components(const request_rec *r, ++ const char **username, ++ const char **password) ++{ ++ const char *auth_header; ++ const char *credentials; ++ const char *decoded; ++ const char *user; ++ ++ auth_header = (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" ++ : "Authorization"; ++ credentials = apr_table_get(r->headers_in, auth_header); ++ ++ if (!credentials) { ++ /* No auth header. */ ++ return APR_EINVAL; ++ } ++ ++ if (strcasecmp(ap_getword(r->pool, &credentials, ' '), "Basic")) { ++ /* These aren't Basic credentials. */ ++ return APR_EINVAL; ++ } ++ ++ while (*credentials == ' ' || *credentials == '\t') { ++ credentials++; ++ } ++ ++ /* XXX Our base64 decoding functions don't actually error out if the string ++ * we give it isn't base64; they'll just silently stop and hand us whatever ++ * they've parsed up to that point. ++ * ++ * Since this function is supposed to be a drop-in replacement for the ++ * deprecated ap_get_basic_auth_pw(), don't fix this for 2.4.x. ++ */ ++ decoded = ap_pbase64decode(r->pool, credentials); ++ user = ap_getword_nulls(r->pool, &decoded, ':'); ++ ++ if (username) { ++ *username = user; ++ } ++ if (password) { ++ *password = decoded; ++ } ++ ++ return APR_SUCCESS; ++} ++ + struct content_length_ctx { + int data_sent; /* true if the C-L filter has already sent at + * least one bucket on to the next output filter +diff --git server/request.c server/request.c +index 7005ca9..f81bbe0 100644 +--- server/request.c ++++ server/request.c +@@ -179,6 +179,14 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + r->ap_auth_type = r->prev->ap_auth_type; + } + else { ++ /* A module using a confusing API (ap_get_basic_auth_pw) caused ++ ** r->user to be filled out prior to check_authn hook. We treat ++ ** it is inadvertent. ++ */ ++ if (r->user && apr_table_get(r->notes, AP_GET_BASIC_AUTH_PW_NOTE)) { ++ r->user = NULL; ++ } ++ + switch (ap_satisfies(r)) { + case SATISFY_ALL: + case SATISFY_NOSPEC: diff --git a/CVE-2017-3169.patch b/CVE-2017-3169.patch new file mode 100644 index 0000000..c423b4c --- /dev/null +++ b/CVE-2017-3169.patch @@ -0,0 +1,76 @@ + + Merge https://svn.apache.org/r1796343 from trunk: + + *) SECURITY: CVE-2017-3169 (cve.mitre.org) + mod_ssl may dereference a NULL pointer when third-party modules call + ap_hook_process_connection() during an HTTP request to an HTTPS port. + [Yann Ylavic] + + + Submitted By: ylavic + Reviewed By: covener, ylavic, wrowe + +diff --git modules/ssl/ssl_engine_io.c modules/ssl/ssl_engine_io.c +index d6016d3..c633be1 100644 +--- modules/ssl/ssl_engine_io.c ++++ modules/ssl/ssl_engine_io.c +@@ -865,19 +865,20 @@ static apr_status_t ssl_filter_write(ap_filter_t *f, + sizeof(HTTP_ON_HTTPS_PORT) - 1, \ + alloc) + +-static void ssl_io_filter_disable(SSLConnRec *sslconn, ap_filter_t *f) ++static void ssl_io_filter_disable(SSLConnRec *sslconn, ++ bio_filter_in_ctx_t *inctx) + { +- bio_filter_in_ctx_t *inctx = f->ctx; + SSL_free(inctx->ssl); + sslconn->ssl = NULL; + inctx->ssl = NULL; + inctx->filter_ctx->pssl = NULL; + } + +-static apr_status_t ssl_io_filter_error(ap_filter_t *f, ++static apr_status_t ssl_io_filter_error(bio_filter_in_ctx_t *inctx, + apr_bucket_brigade *bb, + apr_status_t status) + { ++ ap_filter_t *f = inctx->f; + SSLConnRec *sslconn = myConnConfig(f->c); + apr_bucket *bucket; + int send_eos = 1; +@@ -891,7 +892,7 @@ static apr_status_t ssl_io_filter_error(ap_filter_t *f, + ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, sslconn->server); + + sslconn->non_ssl_request = NON_SSL_SEND_HDR_SEP; +- ssl_io_filter_disable(sslconn, f); ++ ssl_io_filter_disable(sslconn, inctx); + + /* fake the request line */ + bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); +@@ -1407,7 +1408,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, + * rather than have SSLEngine On configured. + */ + if ((status = ssl_io_filter_connect(inctx->filter_ctx)) != APR_SUCCESS) { +- return ssl_io_filter_error(f, bb, status); ++ return ssl_io_filter_error(inctx, bb, status); + } + + if (is_init) { +@@ -1443,7 +1444,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f, + + /* Handle custom errors. */ + if (status != APR_SUCCESS) { +- return ssl_io_filter_error(f, bb, status); ++ return ssl_io_filter_error(inctx, bb, status); + } + + /* Create a transient bucket out of the decrypted data. */ +@@ -1486,7 +1487,7 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f, + inctx->block = APR_BLOCK_READ; + + if ((status = ssl_io_filter_connect(filter_ctx)) != APR_SUCCESS) { +- return ssl_io_filter_error(f, bb, status); ++ return ssl_io_filter_error(inctx, bb, status); + } + + while (!APR_BRIGADE_EMPTY(bb)) { diff --git a/CVE-2017-7668.patch b/CVE-2017-7668.patch new file mode 100644 index 0000000..4470475 --- /dev/null +++ b/CVE-2017-7668.patch @@ -0,0 +1,30 @@ + + Merge r1796350 from trunk: + + *) SECURITY: CVE-2017-7668 (cve.mitre.org) + The HTTP strict parsing changes added in 2.2.32 and 2.4.24 introduced a + bug in token list parsing, which allows ap_find_token() to search past + the end of its input string. By maliciously crafting a sequence of + request headers, an attacker may be able to cause a segmentation fault, + or to force ap_find_token() to return an incorrect value. + + Submitted By: jchampion + Reviewed By: jchampion, wrowe, ylavic + +diff --git server/util.c server/util.c +index 054cc17..9a805b6 100644 +--- server/util.c ++++ server/util.c +@@ -1513,10 +1513,8 @@ AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok) + + s = (const unsigned char *)line; + for (;;) { +- /* find start of token, skip all stop characters, note NUL +- * isn't a token stop, so we don't need to test for it +- */ +- while (TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) { ++ /* find start of token, skip all stop characters */ ++ while (*s && TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) { + ++s; + } + if (!*s) { diff --git a/CVE-2017-7679.patch b/CVE-2017-7679.patch new file mode 100644 index 0000000..adcd541 --- /dev/null +++ b/CVE-2017-7679.patch @@ -0,0 +1,25 @@ + + Merge r1797550 from trunk: + + *) SECURITY: CVE-2017-7679 (cve.mitre.org) + mod_mime can read one byte past the end of a buffer when sending a + malicious Content-Type response header. [Yann Ylavic] + + Submitted By: ylavic + +diff --git modules/http/mod_mime.c modules/http/mod_mime.c +index eed6ebd..f3c643c 100644 +--- modules/http/mod_mime.c ++++ modules/http/mod_mime.c +@@ -528,9 +528,9 @@ static int is_quoted_pair(const char *s) + int res = -1; + int c; + +- if (((s + 1) != NULL) && (*s == '\\')) { ++ if (*s == '\\') { + c = (int) *(s + 1); +- if (apr_isascii(c)) { ++ if (c && apr_isascii(c)) { + res = 1; + } + } diff --git a/apache.spec b/apache.spec index a280dd7..5608b6a 100644 --- a/apache.spec +++ b/apache.spec @@ -44,7 +44,7 @@ Summary(ru.UTF-8): Самый популярный веб-сервер Summary(tr.UTF-8): Lider WWW tarayıcı Name: apache Version: 2.2.32 -Release: 1 +Release: 2 License: Apache v2.0 Group: Networking/Daemons/HTTP Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.gz @@ -85,16 +85,16 @@ Patch1: %{name}-layout.patch Patch2: %{name}-suexec.patch Patch3: %{name}-branding.patch Patch4: %{name}-apr.patch -Patch5: apache-bug-49058.patch +Patch5: %{name}-bug-49058.patch # what about this? it isn't applied... Patch6: httpd-2.0.40-xfsz.patch Patch7: %{name}-syslibs.patch Patch8: httpd-2.0.45-encode.patch Patch9: %{name}-paths.patch Patch10: httpd-2.0.46-dav401dest.patch -Patch11: apache-bug-39311-preforkonly.patch +Patch11: %{name}-bug-39311-preforkonly.patch Patch12: httpd-2.0.46-sslmutex.patch -Patch13: apache-bug-50002.patch +Patch13: %{name}-bug-50002.patch Patch14: httpd-2.0.48-corelimit.patch Patch15: httpd-2.0.48-debuglog.patch Patch18: %{name}-v6only-ENOPROTOOPT.patch @@ -104,12 +104,17 @@ Patch23: %{name}-suexec_fcgi.patch Patch24: %{name}-bug-48094.patch # http://scripts.mit.edu/trac/browser/trunk/server/common/patches/httpd-2.2.x-mod_ssl-sessioncaching.patch?rev=1348 Patch25: httpd-2.2.x-mod_ssl-sessioncaching.patch -Patch26: apache-mod_vhost_alias_docroot.patch +Patch26: %{name}-mod_vhost_alias_docroot.patch # http://mpm-itk.sesse.net/ -Patch28: apache-mpm-itk.patch +Patch28: %{name}-mpm-itk.patch Patch29: libtool-tag.patch -Patch30: apache-bug-39653.patch +Patch30: %{name}-bug-39653.patch Patch31: httpd-dummy-connection-result.patch +# https://www.apache.org/dist/httpd/patches/apply_to_2.2.32/ +Patch32: CVE-2017-3167.patch +Patch33: CVE-2017-3169.patch +Patch34: CVE-2017-7668.patch +Patch35: CVE-2017-7679.patch URL: http://httpd.apache.org/ BuildRequires: apr-devel >= %{apr_ver} BuildRequires: apr-util-devel >= 1:1.3.10-2 @@ -1808,6 +1813,10 @@ Dwa programy testowe/przykładowe cgi: test-cgi and print-env. %patch29 -p1 %patch30 -p1 %patch31 -p1 +%patch32 -p0 +%patch33 -p0 +%patch34 -p0 +%patch35 -p0 # using system apr, apr-util and pcre %{__rm} -r srclib/{apr,apr-util,pcre} @@ -1939,7 +1948,7 @@ install -d $RPM_BUILD_ROOT/etc/{logrotate.d,rc.d/init.d,sysconfig,systemd/system $RPM_BUILD_ROOT%{_var}/{log/{httpd,archive/httpd},{run,cache}/httpd,lock/mod_dav} \ $RPM_BUILD_ROOT%{_sysconfdir}/{webapps.d,conf.d,vhosts.d} \ $RPM_BUILD_ROOT%{_datadir}/{cgi-bin,vhosts} \ - $RPM_BUILD_ROOT/usr/lib/tmpfiles.d \ + $RPM_BUILD_ROOT%{systemdtmpfilesdir} \ $RPM_BUILD_ROOT%{systemdunitdir} # prefork is default one @@ -2003,7 +2012,7 @@ cp -a %{SOURCE21} $CFG/10_mpm.conf cp -a %{SOURCE22} $CFG/20_languages.conf cp -a %{SOURCE29} $RPM_BUILD_ROOT%{_sysconfdir}/vhosts.d/example.net.conf -install %{SOURCE30} $RPM_BUILD_ROOT/usr/lib/tmpfiles.d/%{name}.conf +cp -p %{SOURCE30} $RPM_BUILD_ROOT%{systemdtmpfilesdir}/%{name}.conf echo "LoadModule alias_module modules/mod_alias.so" > $CFG/00_mod_alias.conf echo "LoadModule authn_file_module modules/mod_authn_file.so" > $CFG/00_mod_authn_file.conf @@ -2401,7 +2410,7 @@ fi %dir %attr(770,root,http) /var/run/httpd %dir %attr(770,root,http) /var/cache/httpd -/usr/lib/tmpfiles.d/%{name}.conf +%{systemdtmpfilesdir}/%{name}.conf %{systemdunitdir}/httpd-*.service %config(noreplace) %verify(not md5 mtime size) /etc/systemd/system/httpd.service