Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian....@packages.debian.org
Usertags: pu

Hi,

please review the update for apache2 for inclusion into s-p-u. It fixes
a low-impact security issue and also includes two one-line bug fixes.

The changelog is below, debdiff is attached.

As I couldn't find any mail about it, I guess that 7.8 "Not yet planned;
likely mid-December" is not yet closed?

Thanks in advance.

Cheers,
Stefan


   * CVE-2013-5704: Fix handling of chunk trailers. A remote attacker could
     use this flaw to bypass intended mod_headers restrictions, allowing
     them to send requests to applications that include headers that should
     have been removed by mod_headers.
     The new behavior is to not merge trailers into the headers autmatically.
     A new directive "MergeTrailers" is introduced to restore the old
     behavior.
   * Fix hostname comparison with SNI to be case insensitive. Closes: #771199
   * Fix valule of SSL_CLIENT_S_DN_UID in mod_ssl (broken in 2.2.15).
     Closes: #773841
   * Add paragraph about session ticket key life-time and forward secrecy to
     README.Debian. Closes: #762619


 README.Debian                            |   15 +
 changelog                                |   17 +
 patches/CVE-2013-5704_trailers.patch     |  383 +++++++++++++++++++++++++++++++
 patches/SNI_case_insensitve.diff         |   13 +
 patches/mod_ssl_SSL_CLIENT_S_DN_UID.diff |   13 +
 patches/series                           |    3 
diff -Nru apache2-2.2.22/debian/changelog apache2-2.2.22/debian/changelog
--- apache2-2.2.22/debian/changelog	2014-07-24 17:32:33.000000000 +0200
+++ apache2-2.2.22/debian/changelog	2014-12-23 23:44:50.000000000 +0100
@@ -1,3 +1,20 @@
+apache2 (2.2.22-13+deb7u4) wheezy; urgency=medium
+
+  * CVE-2013-5704: Fix handling of chunk trailers. A remote attacker could
+    use this flaw to bypass intended mod_headers restrictions, allowing
+    them to send requests to applications that include headers that should
+    have been removed by mod_headers.
+    The new behavior is to not merge trailers into the headers autmatically.
+    A new directive "MergeTrailers" is introduced to restore the old
+    behavior.
+  * Fix hostname comparison with SNI to be case insensitive. Closes: #771199
+  * Fix valule of SSL_CLIENT_S_DN_UID in mod_ssl (broken in 2.2.15).
+    Closes: #773841
+  * Add paragraph about session ticket key life-time and forward secrecy to
+    README.Debian. Closes: #762619
+
+ -- Stefan Fritsch <s...@debian.org>  Tue, 23 Dec 2014 23:44:24 +0100
+
 apache2 (2.2.22-13+deb7u3) wheezy-security; urgency=high
 
   * CVE-2014-0226: Fix a race condition in scoreboard handling,
diff -Nru apache2-2.2.22/debian/patches/CVE-2013-5704_trailers.patch apache2-2.2.22/debian/patches/CVE-2013-5704_trailers.patch
--- apache2-2.2.22/debian/patches/CVE-2013-5704_trailers.patch	1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/CVE-2013-5704_trailers.patch	2014-12-22 21:59:22.000000000 +0100
@@ -0,0 +1,383 @@
+# http://svn,apache.org/r1619489
+#
+#  *) SECURITY: CVE-2013-5704 (cve.mitre.org)
+#     core: HTTP trailers could be used to replace HTTP headers
+#     late during request processing, potentially undoing or
+#     otherwise confusing modules that examined or modified
+#     request headers earlier.  Adds "MergeTrailers" directive to restore
+#     legacy behavior.  [Edward Lu, Yann Ylavic, Joe Orton, Eric Covener]
+#
+Index: apache2/modules/loggers/mod_log_config.c
+===================================================================
+--- apache2.orig/modules/loggers/mod_log_config.c
++++ apache2/modules/loggers/mod_log_config.c
+@@ -412,6 +412,12 @@
+     return ap_escape_logitem(r->pool, apr_table_get(r->headers_in, a));
+ }
+ 
++static const char *log_trailer_in(request_rec *r, char *a)
++{
++    return ap_escape_logitem(r->pool, apr_table_get(r->trailers_in, a));
++}
++
++
+ static APR_INLINE char *find_multiple_headers(apr_pool_t *pool,
+                                               const apr_table_t *table,
+                                               const char *key)
+@@ -495,6 +501,11 @@
+     return ap_escape_logitem(r->pool, cp);
+ }
+ 
++static const char *log_trailer_out(request_rec *r, char *a)
++{
++    return ap_escape_logitem(r->pool, apr_table_get(r->trailers_out, a));
++}
++
+ static const char *log_note(request_rec *r, char *a)
+ {
+     return ap_escape_logitem(r->pool, apr_table_get(r->notes, a));
+@@ -813,7 +824,7 @@
+ static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
+ {
+     const char *s = *sa;
+-    ap_log_handler *handler;
++    ap_log_handler *handler = NULL;
+ 
+     if (*s != '%') {
+         return parse_log_misc_string(p, it, sa);
+@@ -883,7 +894,16 @@
+             break;
+ 
+         default:
+-            handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
++            /* check for '^' + two character format first */
++            if (*s == '^' && *(s+1) && *(s+2)) { 
++                handler = (ap_log_handler *)apr_hash_get(log_hash, s, 3); 
++                if (handler) { 
++                   s += 3;
++                }
++            }
++            if (!handler) {  
++                handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);  
++            }
+             if (!handler) {
+                 char dummy[2];
+ 
+@@ -1389,7 +1409,7 @@
+     log_struct->func = handler;
+     log_struct->want_orig_default = def;
+ 
+-    apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
++    apr_hash_set(log_hash, tag, strlen(tag), (const void *)log_struct);
+ }
+ static ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle)
+ {
+@@ -1558,6 +1578,9 @@
+         log_pfn_register(p, "U", log_request_uri, 1);
+         log_pfn_register(p, "s", log_status, 1);
+         log_pfn_register(p, "R", log_handler, 1);
++
++        log_pfn_register(p, "^ti", log_trailer_in, 0);
++        log_pfn_register(p, "^to", log_trailer_out, 0);
+     }
+ 
+     /* reset to default conditions */
+Index: apache2/modules/http/http_request.c
+===================================================================
+--- apache2.orig/modules/http/http_request.c
++++ apache2/modules/http/http_request.c
+@@ -384,8 +384,10 @@
+     new->main            = r->main;
+ 
+     new->headers_in      = r->headers_in;
++    new->trailers_in     = r->trailers_in;
+     new->headers_out     = apr_table_make(r->pool, 12);
+     new->err_headers_out = r->err_headers_out;
++    new->trailers_out    = apr_table_make(r->pool, 5);
+     new->subprocess_env  = rename_original_env(r->pool, r->subprocess_env);
+     new->notes           = apr_table_make(r->pool, 5);
+ 
+@@ -495,6 +497,8 @@
+                                        r->headers_out);
+     r->err_headers_out = apr_table_overlay(r->pool, rr->err_headers_out,
+                                            r->err_headers_out);
++    r->trailers_out = apr_table_overlay(r->pool, rr->trailers_out,
++                                           r->trailers_out);
+     r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env,
+                                           r->subprocess_env);
+ 
+Index: apache2/modules/http/http_filters.c
+===================================================================
+--- apache2.orig/modules/http/http_filters.c
++++ apache2/modules/http/http_filters.c
+@@ -206,6 +206,49 @@
+ }
+ 
+ 
++static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f,
++                                          apr_bucket_brigade *b, int merge)
++{
++    int rv;
++    apr_bucket *e;
++    request_rec *r = f->r;
++    apr_table_t *saved_headers_in = r->headers_in;
++    int saved_status = r->status;
++
++    r->status = HTTP_OK;
++    r->headers_in = r->trailers_in;
++    apr_table_clear(r->headers_in);
++    ctx->state = BODY_NONE;
++    ap_get_mime_headers(r);
++
++    if(r->status == HTTP_OK) {
++        r->status = saved_status;
++        e = apr_bucket_eos_create(f->c->bucket_alloc);
++        APR_BRIGADE_INSERT_TAIL(b, e);
++        ctx->eos_sent = 1;
++        rv = APR_SUCCESS;
++    }
++    else {
++        const char *error_notes = apr_table_get(r->notes,
++                                                "error-notes");
++        ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 
++                      "Error while reading HTTP trailer: %i%s%s",
++                      r->status, error_notes ? ": " : "",
++                      error_notes ? error_notes : "");
++        rv = APR_EINVAL;
++    }
++
++    if(!merge) {
++        r->headers_in = saved_headers_in;
++    }
++    else {
++        r->headers_in = apr_table_overlay(r->pool, saved_headers_in,
++                r->trailers_in);
++    }
++
++    return rv;
++}
++
+ /* This is the HTTP_INPUT filter for HTTP requests and responses from
+  * proxied servers (mod_proxy).  It handles chunked and content-length
+  * bodies.  This can only be inserted/used after the headers
+@@ -215,6 +258,7 @@
+                             ap_input_mode_t mode, apr_read_type_e block,
+                             apr_off_t readbytes)
+ {
++    core_server_config *conf;
+     apr_bucket *e;
+     http_ctx_t *ctx = f->ctx;
+     apr_status_t rv;
+@@ -222,6 +266,9 @@
+     int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE;
+     apr_bucket_brigade *bb;
+ 
++    conf = (core_server_config *)
++        ap_get_module_config(f->r->server->module_config, &core_module);
++
+     /* just get out of the way of things we don't want. */
+     if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
+         return ap_get_brigade(f->next, b, mode, block, readbytes);
+@@ -395,13 +442,8 @@
+             }
+ 
+             if (!ctx->remaining) {
+-                /* Handle trailers by calling ap_get_mime_headers again! */
+-                ctx->state = BODY_NONE;
+-                ap_get_mime_headers(f->r);
+-                e = apr_bucket_eos_create(f->c->bucket_alloc);
+-                APR_BRIGADE_INSERT_TAIL(b, e);
+-                ctx->eos_sent = 1;
+-                return APR_SUCCESS;
++                return read_chunked_trailers(ctx, f, b,
++                        conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE);
+             }
+         }
+     }
+@@ -501,13 +543,8 @@
+                 }
+ 
+                 if (!ctx->remaining) {
+-                    /* Handle trailers by calling ap_get_mime_headers again! */
+-                    ctx->state = BODY_NONE;
+-                    ap_get_mime_headers(f->r);
+-                    e = apr_bucket_eos_create(f->c->bucket_alloc);
+-                    APR_BRIGADE_INSERT_TAIL(b, e);
+-                    ctx->eos_sent = 1;
+-                    return APR_SUCCESS;
++                    return read_chunked_trailers(ctx, f, b,
++                            conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE);
+                 }
+             }
+             break;
+Index: apache2/modules/proxy/proxy_util.c
+===================================================================
+--- apache2.orig/modules/proxy/proxy_util.c
++++ apache2/modules/proxy/proxy_util.c
+@@ -350,8 +350,11 @@
+     rp->status          = HTTP_OK;
+ 
+     rp->headers_in      = apr_table_make(r->pool, 50);
++    rp->trailers_in     = apr_table_make(r->pool, 5);
++
+     rp->subprocess_env  = apr_table_make(r->pool, 50);
+     rp->headers_out     = apr_table_make(r->pool, 12);
++    rp->trailers_out    = apr_table_make(r->pool, 5);
+     rp->err_headers_out = apr_table_make(r->pool, 5);
+     rp->notes           = apr_table_make(r->pool, 5);
+ 
+Index: apache2/modules/proxy/mod_proxy_http.c
+===================================================================
+--- apache2.orig/modules/proxy/mod_proxy_http.c
++++ apache2/modules/proxy/mod_proxy_http.c
+@@ -1229,6 +1229,7 @@
+     psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
+ 
+     r->headers_out = apr_table_make(r->pool, 20);
++    r->trailers_out = apr_table_make(r->pool, 5);
+     *pread_len = 0;
+ 
+     /*
+@@ -1355,6 +1356,14 @@
+ #define AP_MAX_INTERIM_RESPONSES 10
+ #endif
+ 
++static int add_trailers(void *data, const char *key, const char *val)
++{
++    if (val) {
++        apr_table_add((apr_table_t*)data, key, val);
++    }
++    return 1;
++}
++
+ static
+ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
+                                             proxy_conn_rec *backend,
+@@ -1808,6 +1817,12 @@
+                     /* next time try a non-blocking read */
+                     mode = APR_NONBLOCK_READ;
+ 
++                    if (!apr_is_empty_table(rp->trailers_in)) {
++                        apr_table_do(add_trailers, r->trailers_out,
++                                rp->trailers_in, NULL);
++                        apr_table_clear(rp->trailers_in);
++                    }
++
+                     apr_brigade_length(bb, 0, &readbytes);
+                     backend->worker->s->read += readbytes;
+ #if DEBUGGING
+Index: apache2/include/httpd.h
+===================================================================
+--- apache2.orig/include/httpd.h
++++ apache2/include/httpd.h
+@@ -1006,6 +1006,11 @@
+  * record to improve 64bit alignment the next time we need to break
+  * binary compatibility for some other reason.
+  */
++
++    /** MIME trailer environment from the request */
++    apr_table_t *trailers_in;
++    /** MIME trailer environment from the response */
++    apr_table_t *trailers_out;
+ };
+ 
+ /**
+Index: apache2/include/http_core.h
+===================================================================
+--- apache2.orig/include/http_core.h
++++ apache2/include/http_core.h
+@@ -613,6 +613,10 @@
+ #define AP_TRACE_ENABLE    1
+ #define AP_TRACE_EXTENDED  2
+     int trace_enable;
++#define AP_MERGE_TRAILERS_UNSET    0
++#define AP_MERGE_TRAILERS_ENABLE   1
++#define AP_MERGE_TRAILERS_DISABLE  2
++    int merge_trailers;
+ 
+ } core_server_config;
+ 
+Index: apache2/server/protocol.c
+===================================================================
+--- apache2.orig/server/protocol.c
++++ apache2/server/protocol.c
+@@ -708,6 +708,8 @@
+                 r->status = HTTP_REQUEST_TIME_OUT;
+             }
+             else {
++                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, 
++                              "Failed to read request header line %s", field);
+                 r->status = HTTP_BAD_REQUEST;
+             }
+ 
+@@ -887,9 +889,11 @@
+     r->allowed_methods = ap_make_method_list(p, 2);
+ 
+     r->headers_in      = apr_table_make(r->pool, 25);
++    r->trailers_in     = apr_table_make(r->pool, 5);
+     r->subprocess_env  = apr_table_make(r->pool, 25);
+     r->headers_out     = apr_table_make(r->pool, 12);
+     r->err_headers_out = apr_table_make(r->pool, 5);
++    r->trailers_out    = apr_table_make(r->pool, 5);
+     r->notes           = apr_table_make(r->pool, 5);
+ 
+     r->request_config  = ap_create_request_config(r->pool);
+@@ -1117,7 +1121,8 @@
+ 
+     rnew->status          = HTTP_OK;
+ 
+-    rnew->headers_in = apr_table_copy(rnew->pool, r->headers_in);
++    rnew->headers_in      = apr_table_copy(rnew->pool, r->headers_in);
++    rnew->trailers_in     = apr_table_copy(rnew->pool, r->trailers_in);
+ 
+     /* did the original request have a body?  (e.g. POST w/SSI tags)
+      * if so, make sure the subrequest doesn't inherit body headers
+@@ -1129,6 +1134,7 @@
+     rnew->subprocess_env  = apr_table_copy(rnew->pool, r->subprocess_env);
+     rnew->headers_out     = apr_table_make(rnew->pool, 5);
+     rnew->err_headers_out = apr_table_make(rnew->pool, 5);
++    rnew->trailers_out    = apr_table_make(rnew->pool, 5);
+     rnew->notes           = apr_table_make(rnew->pool, 5);
+ 
+     rnew->expecting_100   = r->expecting_100;
+Index: apache2/server/core.c
+===================================================================
+--- apache2.orig/server/core.c
++++ apache2/server/core.c
+@@ -542,6 +542,10 @@
+                          ? virt->trace_enable
+                          : base->trace_enable;
+ 
++    conf->merge_trailers = (virt->merge_trailers != AP_MERGE_TRAILERS_UNSET)
++                           ? virt->merge_trailers
++                           : base->merge_trailers;
++
+     return conf;
+ }
+ 
+@@ -3295,6 +3299,16 @@
+     return NULL;
+ }
+ 
++static const char *set_merge_trailers(cmd_parms *cmd, void *dummy, int arg)
++{
++    core_server_config *conf = ap_get_module_config(cmd->server->module_config,
++                                                    &core_module);
++    conf->merge_trailers = (arg ? AP_MERGE_TRAILERS_ENABLE :
++            AP_MERGE_TRAILERS_DISABLE);
++
++    return NULL;
++}
++
+ /* Note --- ErrorDocument will now work from .htaccess files.
+  * The AllowOverride of Fileinfo allows webmasters to turn it off
+  */
+@@ -3534,6 +3548,8 @@
+ AP_INIT_FLAG("Suexec", unixd_set_suexec, NULL, RSRC_CONF,
+              "Enable or disable suEXEC support"),
+ #endif
++AP_INIT_FLAG("MergeTrailers", set_merge_trailers, NULL, RSRC_CONF,
++              "merge request trailers into request headers or not"),
+ { NULL }
+ };
+ 
diff -Nru apache2-2.2.22/debian/patches/mod_ssl_SSL_CLIENT_S_DN_UID.diff apache2-2.2.22/debian/patches/mod_ssl_SSL_CLIENT_S_DN_UID.diff
--- apache2-2.2.22/debian/patches/mod_ssl_SSL_CLIENT_S_DN_UID.diff	1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/mod_ssl_SSL_CLIENT_S_DN_UID.diff	2014-12-23 23:26:38.000000000 +0100
@@ -0,0 +1,13 @@
+# http://svn.apache.org/viewvc?view=revision&revision=1445112
+# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=773841
+--- apache2.orig/modules/ssl/ssl_engine_vars.c
++++ apache2/modules/ssl/ssl_engine_vars.c
+@@ -431,7 +431,7 @@ static const struct {
+     { "S",     NID_surname,                1 },
+     { "D",     NID_description,            1 },
+ #ifdef NID_userId
+-    { "UID",   NID_x500UniqueIdentifier,   1 },
++    { "UID",   NID_userId,                 1 },
+ #endif
+     { "Email", NID_pkcs9_emailAddress,     1 },
+     { NULL,    0,                          0 }
diff -Nru apache2-2.2.22/debian/patches/series apache2-2.2.22/debian/patches/series
--- apache2-2.2.22/debian/patches/series	2014-07-23 23:26:50.000000000 +0200
+++ apache2-2.2.22/debian/patches/series	2014-12-23 23:22:05.000000000 +0100
@@ -45,3 +45,6 @@
 CVE-2014-0226_scoreboard.patch
 CVE-2014-0231_mod_cgid-DoS.patch
 CVE-2014-0118_mod_deflate-DoS.patch
+CVE-2013-5704_trailers.patch
+SNI_case_insensitve.diff
+mod_ssl_SSL_CLIENT_S_DN_UID.diff
diff -Nru apache2-2.2.22/debian/patches/SNI_case_insensitve.diff apache2-2.2.22/debian/patches/SNI_case_insensitve.diff
--- apache2-2.2.22/debian/patches/SNI_case_insensitve.diff	1970-01-01 01:00:00.000000000 +0100
+++ apache2-2.2.22/debian/patches/SNI_case_insensitve.diff	2014-12-23 23:09:09.000000000 +0100
@@ -0,0 +1,13 @@
+# https://svn.apache.org/viewvc?view=revision&revision=r1515565
+# http://bugs.debian.org/771199
+--- apache2.orig/modules/ssl/ssl_engine_kernel.c
++++ apache2/modules/ssl/ssl_engine_kernel.c
+@@ -136,7 +136,7 @@ int ssl_hook_ReadReq(request_rec *r)
+         if (rv != APR_SUCCESS || scope_id) {
+             return HTTP_BAD_REQUEST;
+         }
+-        if (strcmp(host, servername)) {
++        if (strcasecmp(host, servername)) {
+             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+                         "Hostname %s provided via SNI and hostname %s provided"
+                         " via HTTP are different", servername, host);
diff -Nru apache2-2.2.22/debian/README.Debian apache2-2.2.22/debian/README.Debian
--- apache2-2.2.22/debian/README.Debian	2014-07-23 22:56:40.000000000 +0200
+++ apache2-2.2.22/debian/README.Debian	2014-12-23 23:41:18.000000000 +0100
@@ -11,6 +11,8 @@
 		Enabling SSL
 		Creating self-signed certificates
 		SSL workaround for MSIE
+		ECC keys and ECDH ciphers
+		Session ticket key life-time and forward secrecy
 
 	Suexec
 	
@@ -246,6 +248,19 @@
 A special compatibility fix for older Safari browsers is enabled if using an
 up-to-date libssl-1.0.0 (version 1.0.1e-2+deb7u8 or newer).
 
+Session ticket key life-time and forward secrecy
+------------------------------------------------
+
+Apache uses TLS session tickets to improve handshake performance. By default, a
+new session key key is (re-)generated at startup and at every graceful restart.
+This means that an attacker that somehow gets access to the memory of the
+running apache process may decrypt past connections that have used the current
+session ticket key. This breaks forward secrecy even if the used cipher would
+have provided forward secrecy. There is currently no way to change Apache's
+behavior. If you want to mitigate this kind of attack, you should consider
+increasing the frequency of graceful restarts by changing the log rotation in
+/etc/logrotate.d/apache2 from weekly to daily.
+
 
 Suexec
 ======

Reply via email to