diff options
author | Stefan Fritsch <sf@debian.org> | 2009-11-07 13:35:44 +0000 |
---|---|---|
committer | Stefan Fritsch <sf@sfritsch.de> | 2012-01-02 10:37:05 +0100 |
commit | 951d27693a7f11360aedc8b10db9909f98c7e313 (patch) | |
tree | dae23c1ec20a614eee150691011d511f2fa0032b | |
parent | 23b71e0a5ef6803a11d96e5360c4f8d1e664e53b (diff) | |
download | apache2-951d27693a7f11360aedc8b10db9909f98c7e313.tar.gz |
Reject any client-initiated SSL/TLS renegotiations. This is a partial fix
for the TLS renegotiation prefix injection attack (CVE-2009-3555).
git-svn-id: svn+ssh://svn.debian.org/svn/pkg-apache/trunk/apache2@1088 01b336ce-410b-0410-9a02-a0e7f243c266
-rw-r--r-- | debian/changelog | 5 | ||||
-rw-r--r-- | debian/patches/00list | 1 | ||||
-rw-r--r-- | debian/patches/072_CVE-2009-3555.dpatch | 313 |
3 files changed, 319 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog index e6366033..f4c945ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,10 @@ apache2 (2.2.14-2) UNRELEASED; urgency=low + * Security: + Reject any client-initiated SSL/TLS renegotiations. This is a partial fix + for the TLS renegotiation prefix injection attack (CVE-2009-3555). + Any configuration which requires renegotiation for per-directory/location + access control is still vulnerable. * Allow RemoveType to override the types from /etc/mime.types. This allows to use .es and .tr for Spanish and Turkish files in mod_negotiation. Closes: #496080 diff --git a/debian/patches/00list b/debian/patches/00list index f5c68732..d130cd86 100644 --- a/debian/patches/00list +++ b/debian/patches/00list @@ -21,6 +21,7 @@ 069_no_deflate_for_HEAD.dpatch 070_RemoveType_override_mime.types.dpatch 071_fix_cacheenable.dpatch +072_CVE-2009-3555.dpatch 099_config_guess_sub_update 200_cp_suexec.dpatch 201_build_suexec-custom.dpatch diff --git a/debian/patches/072_CVE-2009-3555.dpatch b/debian/patches/072_CVE-2009-3555.dpatch new file mode 100644 index 00000000..1031e30f --- /dev/null +++ b/debian/patches/072_CVE-2009-3555.dpatch @@ -0,0 +1,313 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: TLS/SSL partial fix for CVE-2009-3555 + +@DPATCH@ + *) SECURITY: CVE-2009-3555 (cve.mitre.org) + A partial fix for the TLS renegotiation prefix injection attack by + rejecting any client-initiated renegotiations. Any configuration + which requires renegotiation for per-directory/location access + control is still vulnerable, unless using OpenSSL >= 0.9.8l. + [Joe Orton, Ruediger Pluem] +Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c +URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_init.c?rev=833622&r1=833621&r2=833622&view=diff +============================================================================== +--- 1/modules/ssl/ssl_engine_init.c (original) ++++ 1/modules/ssl/ssl_engine_init.c Sat Nov 7 00:56:23 2009 +@@ -501,10 +501,7 @@ + SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA); + SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); + +- if (s->loglevel >= APLOG_DEBUG) { +- /* this callback only logs if LogLevel >= info */ +- SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState); +- } ++ SSL_CTX_set_info_callback(ctx, ssl_callback_Info); + } + + static void ssl_init_ctx_verify(server_rec *s, + +Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c +URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_io.c?rev=833622&r1=833621&r2=833622&view=diff +============================================================================== +--- 1/modules/ssl/ssl_engine_io.c (original) ++++ 1/modules/ssl/ssl_engine_io.c Sat Nov 7 00:56:23 2009 +@@ -103,6 +103,7 @@ + ap_filter_t *pInputFilter; + ap_filter_t *pOutputFilter; + int nobuffer; /* non-zero to prevent buffering */ ++ SSLConnRec *config; + } ssl_filter_ctx_t; + + typedef struct { +@@ -193,7 +194,13 @@ + static int bio_filter_out_write(BIO *bio, const char *in, int inl) + { + bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr); +- ++ ++ /* Abort early if the client has initiated a renegotiation. */ ++ if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) { ++ outctx->rc = APR_ECONNABORTED; ++ return -1; ++ } ++ + /* when handshaking we'll have a small number of bytes. + * max size SSL will pass us here is about 16k. + * (16413 bytes to be exact) +@@ -466,6 +473,12 @@ + if (!in) + return 0; + ++ /* Abort early if the client has initiated a renegotiation. */ ++ if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) { ++ inctx->rc = APR_ECONNABORTED; ++ return -1; ++ } ++ + /* XXX: flush here only required for SSLv2; + * OpenSSL calls BIO_flush() at the appropriate times for + * the other protocols. +@@ -1724,6 +1737,8 @@ + + filter_ctx = apr_palloc(c->pool, sizeof(ssl_filter_ctx_t)); + ++ filter_ctx->config = myConnConfig(c); ++ + filter_ctx->nobuffer = 0; + filter_ctx->pOutputFilter = ap_add_output_filter(ssl_io_filter, + filter_ctx, NULL, c); + +Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c +URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_engine_kernel.c?rev=833622&r1=833621&r2=833622&view=diff +============================================================================== +--- 1/modules/ssl/ssl_engine_kernel.c (original) ++++ 1/modules/ssl/ssl_engine_kernel.c Sat Nov 7 00:56:23 2009 +@@ -729,6 +729,10 @@ + (unsigned char *)&id, + sizeof(id)); + ++ /* Toggle the renegotiation state to allow the new ++ * handshake to proceed. */ ++ sslconn->reneg_state = RENEG_ALLOW; ++ + SSL_renegotiate(ssl); + SSL_do_handshake(ssl); + +@@ -750,6 +754,8 @@ + SSL_set_state(ssl, SSL_ST_ACCEPT); + SSL_do_handshake(ssl); + ++ sslconn->reneg_state = RENEG_REJECT; ++ + if (SSL_get_state(ssl) != SSL_ST_OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Re-negotiation handshake failed: " +@@ -1844,76 +1850,55 @@ + return; + } + +-/* +- * This callback function is executed while OpenSSL processes the +- * SSL handshake and does SSL record layer stuff. We use it to +- * trace OpenSSL's processing in out SSL logfile. +- */ +-void ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) ++/* Dump debugginfo trace to the log file. */ ++static void log_tracing_state(MODSSL_INFO_CB_ARG_TYPE ssl, conn_rec *c, ++ server_rec *s, int where, int rc) + { +- conn_rec *c; +- server_rec *s; +- SSLSrvConfigRec *sc; +- +- /* +- * find corresponding server +- */ +- if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { +- return; +- } +- +- s = mySrvFromConn(c); +- if (!(sc = mySrvConfig(s))) { +- return; +- } +- + /* + * create the various trace messages + */ +- if (s->loglevel >= APLOG_DEBUG) { +- if (where & SSL_CB_HANDSHAKE_START) { +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Handshake: start", SSL_LIBRARY_NAME); +- } +- else if (where & SSL_CB_HANDSHAKE_DONE) { +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Handshake: done", SSL_LIBRARY_NAME); +- } +- else if (where & SSL_CB_LOOP) { +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Loop: %s", +- SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); +- } +- else if (where & SSL_CB_READ) { ++ if (where & SSL_CB_HANDSHAKE_START) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "%s: Handshake: start", SSL_LIBRARY_NAME); ++ } ++ else if (where & SSL_CB_HANDSHAKE_DONE) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "%s: Handshake: done", SSL_LIBRARY_NAME); ++ } ++ else if (where & SSL_CB_LOOP) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "%s: Loop: %s", ++ SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); ++ } ++ else if (where & SSL_CB_READ) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "%s: Read: %s", ++ SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); ++ } ++ else if (where & SSL_CB_WRITE) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "%s: Write: %s", ++ SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); ++ } ++ else if (where & SSL_CB_ALERT) { ++ char *str = (where & SSL_CB_READ) ? "read" : "write"; ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, ++ "%s: Alert: %s:%s:%s", ++ SSL_LIBRARY_NAME, str, ++ SSL_alert_type_string_long(rc), ++ SSL_alert_desc_string_long(rc)); ++ } ++ else if (where & SSL_CB_EXIT) { ++ if (rc == 0) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Read: %s", ++ "%s: Exit: failed in %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + } +- else if (where & SSL_CB_WRITE) { ++ else if (rc < 0) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Write: %s", ++ "%s: Exit: error in %s", + SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + } +- else if (where & SSL_CB_ALERT) { +- char *str = (where & SSL_CB_READ) ? "read" : "write"; +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Alert: %s:%s:%s", +- SSL_LIBRARY_NAME, str, +- SSL_alert_type_string_long(rc), +- SSL_alert_desc_string_long(rc)); +- } +- else if (where & SSL_CB_EXIT) { +- if (rc == 0) { +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Exit: failed in %s", +- SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); +- } +- else if (rc < 0) { +- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, +- "%s: Exit: error in %s", +- SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); +- } +- } + } + + /* +@@ -1933,6 +1918,52 @@ + } + } + ++/* ++ * This callback function is executed while OpenSSL processes the SSL ++ * handshake and does SSL record layer stuff. It's used to trap ++ * client-initiated renegotiations, and for dumping everything to the ++ * log. ++ */ ++void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) ++{ ++ conn_rec *c; ++ server_rec *s; ++ SSLConnRec *scr; ++ ++ /* Retrieve the conn_rec and the associated SSLConnRec. */ ++ if ((c = (conn_rec *)SSL_get_app_data((SSL *)ssl)) == NULL) { ++ return; ++ } ++ ++ if ((scr = myConnConfig(c)) == NULL) { ++ return; ++ } ++ ++ /* If the reneg state is to reject renegotiations, check the SSL ++ * state machine and move to ABORT if a Client Hello is being ++ * read. */ ++ if ((where & SSL_CB_ACCEPT_LOOP) && scr->reneg_state == RENEG_REJECT) { ++ int state = SSL_get_state(ssl); ++ ++ if (state == SSL3_ST_SR_CLNT_HELLO_A ++ || state == SSL23_ST_SR_CLNT_HELLO_A) { ++ scr->reneg_state = RENEG_ABORT; ++ ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, ++ "rejecting client initiated renegotiation"); ++ } ++ } ++ /* If the first handshake is complete, change state to reject any ++ * subsequent client-initated renegotiation. */ ++ else if ((where & SSL_CB_HANDSHAKE_DONE) && scr->reneg_state == RENEG_INIT) { ++ scr->reneg_state = RENEG_REJECT; ++ } ++ ++ s = mySrvFromConn(c); ++ if (s && s->loglevel >= APLOG_DEBUG) { ++ log_tracing_state(ssl, c, s, where, rc); ++ } ++} ++ + #ifndef OPENSSL_NO_TLSEXT + /* + * This callback function is executed when OpenSSL encounters an extended + +Modified: httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h +URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/ssl/ssl_private.h?rev=833622&r1=833621&r2=833622&view=diff +============================================================================== +--- 1/modules/ssl/ssl_private.h (original) ++++ 1/modules/ssl/ssl_private.h Sat Nov 7 00:56:23 2009 +@@ -356,6 +356,20 @@ + int is_proxy; + int disabled; + int non_ssl_request; ++ ++ /* Track the handshake/renegotiation state for the connection so ++ * that all client-initiated renegotiations can be rejected, as a ++ * partial fix for CVE-2009-3555. */ ++ enum { ++ RENEG_INIT = 0, /* Before initial handshake */ ++ RENEG_REJECT, /* After initial handshake; any client-initiated ++ * renegotiation should be rejected */ ++ RENEG_ALLOW, /* A server-initated renegotiation is taking ++ * place (as dictated by configuration) */ ++ RENEG_ABORT /* Renegotiation initiated by client, abort the ++ * connection */ ++ } reneg_state; ++ + server_rec *server; + } SSLConnRec; + +@@ -574,7 +588,7 @@ + int ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *); + SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *); + void ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *); +-void ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int); ++void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE, int, int); + #ifndef OPENSSL_NO_TLSEXT + int ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *); + #endif + + |