tags 700399 +patch thanks Hi,
Attached is a proposed update for squeeze-security to address this issue. Upstream's patch for client side renegotiation also fixed the SSL compression issue in the same commit. The SSL compression fix however only works with openssl >= 1. Therefore, I had to backport another fix (the same one as used by Apache) to this version in a second patch. I didn't think it was worthwhile to remove upstream's fix from the renegotiation patch as it's a no-op on squeeze. I have not backported the commit that updates the example configuration file to add an example for the renegotiation option, as this would introduce a config file prompt in stable. I've built the package and we're currently running this on our test environment. It works fine. Also, all compliance tests are now green again. Built packages for amd64 are available at https://lissers.uvt.nl/~thijs/lighttpd/ Do you agree on the approach? Barring any objections I'm planning to release this as a DSA after the weekend. Cheers, Thijs -- Thijs Kinkhorst <th...@uvt.nl> – LIS Unix Universiteit van Tilburg – Library and IT Services • Postbus 90153, 5000 LE Bezoekadres > Warandelaan 2 • Tel. 013 466 3035 • G 236 • http://www.uvt.nl
diff -Nru lighttpd-1.4.28/debian/changelog lighttpd-1.4.28/debian/changelog --- lighttpd-1.4.28/debian/changelog 2011-12-20 21:53:07.000000000 +0100 +++ lighttpd-1.4.28/debian/changelog 2013-02-12 14:32:01.000000000 +0100 @@ -1,3 +1,14 @@ +lighttpd (1.4.28-2+squeeze1.1) stable-security; urgency=high + + * Non-maintainer upload by the security team. + * Backport upstream fixes for SSL attacks: + + Disable client triggered renegotiation by default (CVE-2009-3555). + Can be re-enabled with ssl.disable-client-renegotiation = "false". + + Disable SSL compression at build time (CVE-2012-4929, 'CRIME'). + (closes: #700399) + + -- Thijs Kinkhorst <th...@debian.org> Tue, 12 Feb 2013 13:56:53 +0100 + lighttpd (1.4.28-2+squeeze1) stable-security; urgency=high * Backport security issues from 1.4.30: diff -Nru lighttpd-1.4.28/debian/patches/series lighttpd-1.4.28/debian/patches/series --- lighttpd-1.4.28/debian/patches/series 2011-12-20 21:53:07.000000000 +0100 +++ lighttpd-1.4.28/debian/patches/series 2013-02-12 15:24:13.000000000 +0100 @@ -2,3 +2,5 @@ fix-CVE-2011-4362.patch ssl-mitigate-beast.patch debian-changes-1.4.28-2 +ssl-reneg.patch +ssl-crime.patch diff -Nru lighttpd-1.4.28/debian/patches/ssl-crime.patch lighttpd-1.4.28/debian/patches/ssl-crime.patch --- lighttpd-1.4.28/debian/patches/ssl-crime.patch 1970-01-01 01:00:00.000000000 +0100 +++ lighttpd-1.4.28/debian/patches/ssl-crime.patch 2013-02-12 15:22:26.000000000 +0100 @@ -0,0 +1,20 @@ +Description: Disable SSL compression. + Mitigates the SSL CRIME (CVE-2012-4929) attacks. + Upstream patch uses option only present in wheezy openssl, so + this code is needed to actually disable compression in squeeze. +Forwarded: not-needed +Bug-Debian: http://bugs.debian.org/700399 + +diff -Nur lighttpd-1.4.28/src/network.c lighttpd-1.4.28.new/src/network.c +--- lighttpd-1.4.28/src/network.c 2013-02-12 15:20:23.000000000 +0100 ++++ lighttpd-1.4.28.new/src/network.c 2013-02-12 15:19:51.954559635 +0100 +@@ -566,6 +566,9 @@ + } + } + ++ /* Debian: disable ssl compression to mitigate CRIME attack. */ ++ sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); ++ + if (!buffer_is_empty(s->ssl_cipher_list)) { + /* Disable support for low encryption ciphers */ + if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) { diff -Nru lighttpd-1.4.28/debian/patches/ssl-reneg.patch lighttpd-1.4.28/debian/patches/ssl-reneg.patch --- lighttpd-1.4.28/debian/patches/ssl-reneg.patch 1970-01-01 01:00:00.000000000 +0100 +++ lighttpd-1.4.28/debian/patches/ssl-reneg.patch 2013-02-12 15:23:49.000000000 +0100 @@ -0,0 +1,182 @@ +Description: Disable SSL renegotiation. + Mitigates the SSL renegotiation (CVE-2009-3555) attacks. + Introduces a new configuration option: ssl.disable-client-renegotiation, + default true. Upstream also included code to disable SSL compression + in the same commit. This does not work on the openssl in squeeze but + doesn't hurt. +Forwarded: not-needed +Origin: upstream, r2808 r2809 r2812 +Bug-Debian: http://bugs.debian.org/700399 + +Index: b/src/network.c +=================================================================== +--- a/src/network.c 2013-02-12 14:30:59.713970364 +0100 ++++ b/src/network.c 2013-02-12 14:31:00.189958247 +0100 +@@ -27,6 +27,19 @@ + # include <openssl/rand.h> + #endif + ++#ifdef USE_OPENSSL ++static void ssl_info_callback(const SSL *ssl, int where, int ret) { ++ UNUSED(ret); ++ ++ if (0 != (where & SSL_CB_HANDSHAKE_START)) { ++ connection *con = SSL_get_app_data(ssl); ++ ++con->renegotiations; ++ } else if (0 != (where & SSL_CB_HANDSHAKE_DONE)) { ++ ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; ++ } ++} ++#endif ++ + static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) { + server_socket *srv_socket = (server_socket *)context; + connection *con; +@@ -504,6 +517,11 @@ + /* load SSL certificates */ + for (i = 0; i < srv->config_context->used; i++) { + specific_config *s = srv->config_storage[i]; ++#ifndef SSL_OP_NO_COMPRESSION ++# define SSL_OP_NO_COMPRESSION 0 ++#endif ++ long ssloptions = ++ SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION; + + if (buffer_is_empty(s->ssl_pemfile)) continue; + +@@ -536,6 +554,9 @@ + return -1; + } + ++ SSL_CTX_set_options(s->ssl_ctx, ssloptions); ++ SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback); ++ + if (!s->ssl_use_sslv2) { + /* disable SSLv2 */ + if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) { +Index: b/src/base.h +=================================================================== +--- a/src/base.h 2013-02-12 14:30:59.709970466 +0100 ++++ b/src/base.h 2013-02-12 14:31:00.193958145 +0100 +@@ -282,6 +282,7 @@ + unsigned short ssl_verifyclient_depth; + buffer *ssl_verifyclient_username; + unsigned short ssl_verifyclient_export_cert; ++ unsigned short ssl_disable_client_renegotiation; + + unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */ + unsigned short defer_accept; +@@ -435,6 +436,7 @@ + # ifndef OPENSSL_NO_TLSEXT + buffer *tlsext_server_name; + # endif ++ unsigned int renegotiations; /* count of SSL_CB_HANDSHAKE_START */ + #endif + /* etag handling */ + etag_flags_t etag_flags; +Index: b/src/network_openssl.c +=================================================================== +--- a/src/network_openssl.c 2013-02-12 14:30:56.810044291 +0100 ++++ b/src/network_openssl.c 2013-02-12 14:31:00.193958145 +0100 +@@ -87,7 +87,14 @@ + */ + + ERR_clear_error(); +- if ((r = SSL_write(ssl, offset, toSend)) <= 0) { ++ r = SSL_write(ssl, offset, toSend); ++ ++ if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) { ++ log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client"); ++ return -1; ++ } ++ ++ if (r <= 0) { + unsigned long err; + + switch ((ssl_r = SSL_get_error(ssl, r))) { +@@ -190,7 +197,14 @@ + close(ifd); + + ERR_clear_error(); +- if ((r = SSL_write(ssl, s, toSend)) <= 0) { ++ r = SSL_write(ssl, s, toSend); ++ ++ if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) { ++ log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client"); ++ return -1; ++ } ++ ++ if (r <= 0) { + unsigned long err; + + switch ((ssl_r = SSL_get_error(ssl, r))) { +Index: b/src/connections.c +=================================================================== +--- a/src/connections.c 2013-02-12 14:30:59.285981260 +0100 ++++ b/src/connections.c 2013-02-12 14:31:00.193958145 +0100 +@@ -223,6 +223,12 @@ + + len = SSL_read(con->ssl, b->ptr + read_offset, toread); + ++ if (con->renegotiations > 1 && con->conf.ssl_disable_client_renegotiation) { ++ connection_set_state(srv, con, CON_STATE_ERROR); ++ log_error_write(srv, __FILE__, __LINE__, "s", "SSL: renegotiation initiated by client"); ++ return -1; ++ } ++ + if (len > 0) { + if (b->used > 0) b->used--; + b->used += len; +@@ -1352,6 +1358,7 @@ + return NULL; + } + ++ con->renegotiations = 0; + #ifndef OPENSSL_NO_TLSEXT + SSL_set_app_data(con->ssl, con); + #endif +Index: b/src/configfile.c +=================================================================== +--- a/src/configfile.c 2013-02-12 14:30:59.713970364 +0100 ++++ b/src/configfile.c 2013-02-12 14:31:00.193958145 +0100 +@@ -103,6 +103,7 @@ + + { "server.set-v6only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 61 */ + { "ssl.honor-cipher-order", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER}, /* 62 */ ++ { "ssl.disable-client-renegotiation", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },/* 65 */ + + { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, + { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, +@@ -195,6 +196,7 @@ + s->ssl_verifyclient_username = buffer_init(); + s->ssl_verifyclient_depth = 9; + s->ssl_verifyclient_export_cert = 0; ++ s->ssl_disable_client_renegotiation = 1; + + cv[2].destination = s->errorfile_prefix; + +@@ -249,6 +251,7 @@ + cv[59].destination = s->ssl_verifyclient_username; + cv[60].destination = &(s->ssl_verifyclient_export_cert); + cv[62].destination = &(s->ssl_honor_cipher_order); ++ cv[65].destination = &(s->ssl_disable_client_renegotiation); + + srv->config_storage[i] = s; + +@@ -338,6 +341,7 @@ + PATCH(ssl_verifyclient_depth); + PATCH(ssl_verifyclient_username); + PATCH(ssl_verifyclient_export_cert); ++ PATCH(ssl_disable_client_renegotiation); + + return 0; + } +@@ -442,6 +446,8 @@ + PATCH(ssl_verifyclient_username); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) { + PATCH(ssl_verifyclient_export_cert); ++ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.disable-client-renegotiation"))) { ++ PATCH(ssl_disable_client_renegotiation); + } + } + }
signature.asc
Description: This is a digitally signed message part.