|
View:
New views
18 Messages
—
Rating Filter:
Alert me
|
|
|
TLS renegotiation attack, mod_ssl and OpenSSLWith reference to the issue described here:
http://www.ietf.org/mail-archive/web/tls/current/msg03948.html Considering the impact on mod_ssl, I'm making these assumptions: 1. no HTTP/SSL client initiates a renegotiation of its own accord 2. many mod_ssl configurations do not require a renegotiation to be performed at all 3. some mod_ssl configurations, typically requiring client cert auth in a per-directory/location context, do require the server to initiate a renegotiation. The longer term plan to fix the vulnerability is to upgrade all clients and servers to support a new TLS extension which allows renegotiations to be performed securely. Disabling renegotiation completely and unconditionally at SSL toolkit level will break a significant number of installs - I don't think we could deploy that change. In the short term, I think it would be useful to have a new SSL_OP_* flag which enables rejection of a client-initiated handshake in an SSL server. This will fix the issue for 90% of sites without breaking the remaining 10% (case 3 above), and is a change that can be deployed everywhere. Regards, Joe ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLHi
Isn't the real simple cause the possiblity to 'upgrade' an "anonymous" session to a client authenticated one initiated by the server after seeing a request to a ressource and the problem that the client cannot repeat the request. In case of a GET et consorts, the result of the request is already protected by the new ciphersuite, so the *attacker* cannot do much more that DOS, or (one could respond with a redirect to the same resource to see whether it really comes from the client) In case of a POST et consorts I think one should simply reject the request since it seems always possible to have the post initiated already from an appropriate security context. Either the form is in the same directory, or the whole thing is on another virtual server, i.e. the client has switched already. This are my 3 quarks. Peter Sylvester ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLJoe Orton wrote:
> With reference to the issue described here: > > http://www.ietf.org/mail-archive/web/tls/current/msg03948.html > > Considering the impact on mod_ssl, I'm making these assumptions: > > 1. no HTTP/SSL client initiates a renegotiation of its own accord > > 2. many mod_ssl configurations do not require a renegotiation to be > performed at all > > 3. some mod_ssl configurations, typically requiring client cert auth in > a per-directory/location context, do require the server to initiate a > renegotiation. > > The longer term plan to fix the vulnerability is to upgrade all clients > and servers to support a new TLS extension which allows renegotiations > to be performed securely. > > Disabling renegotiation completely and unconditionally at SSL toolkit > level will break a significant number of installs - I don't think we > could deploy that change. > > In the short term, I think it would be useful to have a new SSL_OP_* > flag which enables rejection of a client-initiated handshake in an SSL > server. This will fix the issue for 90% of sites without breaking the > remaining 10% (case 3 above), and is a change that can be deployed > everywhere. Case 3 is vulnerable to attack, though, so I'm afraid you want to break it. -- http://www.apache-ssl.org/ben.html http://www.links.org/ "There is no limit to what a man can do or how far he can go if he doesn't mind who gets the credit." - Robert Woodruff ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn Thu, Nov 05, 2009 at 03:39:06PM +0000, Ben Laurie wrote:
> Joe Orton wrote: > > In the short term, I think it would be useful to have a new SSL_OP_* > > flag which enables rejection of a client-initiated handshake in an SSL > > server. This will fix the issue for 90% of sites without breaking the > > remaining 10% (case 3 above), and is a change that can be deployed > > everywhere. > > Case 3 is vulnerable to attack, though, so I'm afraid you want to break it. Sites depend on per-dir-reneg and people will simply not upgrade if we break that - I have tried the "don't do that" response for per-dir-reneg issues enough times over the years that I'm reasonably confident of this. (Also I'm told that the Postgres SSL support depends on being able to do a periodic reneg, in the wider context) Being able to ship a 90% solution now and working on the proper fixes for the remaining 10% is valuable, I think. Regards, Joe ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn 11/05/2009 06:32 PM, Joe Orton wrote: > On Thu, Nov 05, 2009 at 03:39:06PM +0000, Ben Laurie wrote: >> Joe Orton wrote: >>> In the short term, I think it would be useful to have a new SSL_OP_* >>> flag which enables rejection of a client-initiated handshake in an SSL >>> server. This will fix the issue for 90% of sites without breaking the >>> remaining 10% (case 3 above), and is a change that can be deployed >>> everywhere. >> Case 3 is vulnerable to attack, though, so I'm afraid you want to break it. > > Sites depend on per-dir-reneg and people will simply not upgrade if we > break that - I have tried the "don't do that" response for per-dir-reneg > issues enough times over the years that I'm reasonably confident of > this. (Also I'm told that the Postgres SSL support depends on being > able to do a periodic reneg, in the wider context) > > Being able to ship a 90% solution now and working on the proper fixes > for the remaining 10% is valuable, I think. I agree with Joe here. See the lengthy discussions we had regarding POST bodies handling in mod_ssl during renegotiation at https://issues.apache.org/bugzilla/show_bug.cgi?id=12355 https://issues.apache.org/bugzilla/show_bug.cgi?id=39243 If server triggered renegotiation will not work at all, people will just ignore the update or remove it from 0.9.8l in their self patched versions. So overall I guess we would be safer with an approach that 1. Turns off renegotiation (server and client) by default. 2. Allows to turn on server and client triggered renegotiation in a way as proposed by Joe. 3. Allow to turn on server triggered renegotiation by a compile time option. 1. This way openssl ships save by default. 2. Consumers of the library can decide to overwrite this behaviour. 3. Packagers can decide to deliver only a "90%" solution if they do not want / cannot modify all consumer packages that need server triggered renegotiation. Some of the attacks rely on specific HTTP mechanisms like connection keep alives and pipelining. So we might be able to find patches for mod_ssl to solve these specific cases. Regards Rüdiger ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn Thu, Nov 05, 2009 at 09:38:23PM +0100, Ruediger Pluem wrote:
> If server triggered renegotiation will not work at all, people will just ignore the > update or remove it from 0.9.8l in their self patched versions. > So overall I guess we would be safer with an approach that > > 1. Turns off renegotiation (server and client) by default. > 2. Allows to turn on server and client triggered renegotiation in a way as proposed > by Joe. > 3. Allow to turn on server triggered renegotiation by a compile time option. In discussion here, Theo Schlossnagle has suggested (and implemented for another SSL server) an approach for (2) which I think we can use for mod_ssl, and doesn't require patching OpenSSL: * we can detect in mod_ssl when the client is renegotiating by using the callback installed using SSL_CTX_set_info_callback(), in conjunction with suitable flags in the SSLConnRec to detect the cases where this is either a server-initiated renegotiation or the initial handshake on the connection. I'll try a patch for this. Regards, Joe ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLJoe Orton wrote:
> * we can detect in mod_ssl when the client is renegotiating by using the > callback installed using SSL_CTX_set_info_callback(), in conjunction > with suitable flags in the SSLConnRec to detect the cases where this is > either a server-initiated renegotiation or the initial handshake on the > connection. This seems to work for me - i.e. it calls back exactly when needed (rather than EAGAIN like break bubbling up in kernel_io.c) - and it _also_ seems to cover the other types of re-negotiation (i.e. other than for a Cert) which actually worry me a lot more. For the record - this MiM can be done with _all_ type of (re)negotiations - for all parameters right ? Thanks, Dw. ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn 11/05/2009 11:03 PM, Dirk-Willem van Gulik wrote: > Joe Orton wrote: > >> * we can detect in mod_ssl when the client is renegotiating by using the >> callback installed using SSL_CTX_set_info_callback(), in conjunction >> with suitable flags in the SSLConnRec to detect the cases where this is >> either a server-initiated renegotiation or the initial handshake on the >> connection. > > This seems to work for me - i.e. it calls back exactly when needed > (rather than EAGAIN like break bubbling up in kernel_io.c) - and it > _also_ seems to cover the other types of re-negotiation (i.e. other than > for a Cert) which actually worry me a lot more. > > For the record - this MiM can be done with _all_ type of > (re)negotiations - for all parameters right ? As far as I understand it: Yes. One of the examples was regarding cipher spec renegotiations and I see no reasons why other renegotiations beyond cert and cipher spec shouldn't be vulnerable. Regards Rüdiger ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn Thu, Nov 05, 2009 at 09:31:00PM +0000, Joe Orton wrote:
> * we can detect in mod_ssl when the client is renegotiating by using the > callback installed using SSL_CTX_set_info_callback(), in conjunction > with suitable flags in the SSLConnRec to detect the cases where this is > either a server-initiated renegotiation or the initial handshake on the > connection. Here is a very rough first hack (for discussion/testing purposes only!): Index: ssl_private.h =================================================================== --- ssl_private.h (revision 832979) +++ ssl_private.h (working copy) @@ -335,6 +335,14 @@ int is_proxy; int disabled; int non_ssl_request; + enum { + RENEG_INIT = 0, /* before initial handshake. */ + RENEG_ALLOW, /* a server-initated renegotiation is taking place */ + RENEG_REJECT, /* after initial handshake; any client-initiated + * renegotiation should be rejected. */ + RENEG_ABORT /* renegotiation initiated by client, abort abort */ + } reneg_state; + server_rec *server; } SSLConnRec; Index: ssl_engine_init.c =================================================================== --- ssl_engine_init.c (revision 832979) +++ ssl_engine_init.c (working copy) @@ -520,7 +520,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) { + if (1 || s->loglevel >= APLOG_DEBUG) { /* this callback only logs if LogLevel >= info */ SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState); } Index: ssl_engine_io.c =================================================================== --- ssl_engine_io.c (revision 832979) +++ ssl_engine_io.c (working copy) @@ -190,10 +190,27 @@ return -1; } +static int conn_in_reneg(conn_rec *c) +{ + SSLConnRec *scr = myConnConfig(c); + + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + "reneg_state == %s", scr->reneg_state == RENEG_INIT ? "INIT" : + scr->reneg_state == RENEG_REJECT ? "REJECT" : + scr->reneg_state == RENEG_ALLOW ? "ALLOW" : "ABORT"); + + return scr->reneg_state == RENEG_ABORT; +} + 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); - + + if (conn_in_reneg(outctx->c)) { + outctx->rc = APR_EACCES; + 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) @@ -476,6 +493,11 @@ if (!in) return 0; + if (conn_in_reneg(inctx->f->c)) { + inctx->rc = APR_EACCES; + return -1; + } + /* In theory, OpenSSL should flush as necessary, but it is known * not to do so correctly in some cases; see PR 46952. * Index: ssl_engine_kernel.c =================================================================== --- ssl_engine_kernel.c (revision 832979) +++ ssl_engine_kernel.c (working copy) @@ -733,6 +733,8 @@ (unsigned char *)&id, sizeof(id)); + sslconn->reneg_state = RENEG_ALLOW; + SSL_renegotiate(ssl); SSL_do_handshake(ssl); @@ -754,6 +756,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: " @@ -1824,7 +1828,8 @@ conn_rec *c; server_rec *s; SSLSrvConfigRec *sc; - + SSLConnRec *scr; + /* * find corresponding server */ @@ -1837,6 +1842,18 @@ return; } + scr = myConnConfig(c); + + { + int state = SSL_get_state(ssl); + + if (scr->reneg_state == RENEG_REJECT + && (state == SSL3_ST_SR_CLNT_HELLO_A + || state == SSL23_ST_SR_CLNT_HELLO_A)) { + scr->reneg_state = RENEG_ABORT; + } + } + /* * create the various trace messages */ @@ -1900,6 +1917,9 @@ ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER"), ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_USEKEYSIZE"), ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_ALGKEYSIZE")); + if (scr->reneg_state == RENEG_INIT) { + scr->reneg_state = RENEG_REJECT; + } } } ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn Fri, Nov 06, 2009 at 12:00:06AM +0000, Joe Orton wrote:
> On Thu, Nov 05, 2009 at 09:31:00PM +0000, Joe Orton wrote: > > * we can detect in mod_ssl when the client is renegotiating by using the > > callback installed using SSL_CTX_set_info_callback(), in conjunction > > with suitable flags in the SSLConnRec to detect the cases where this is > > either a server-initiated renegotiation or the initial handshake on the > > connection. > > Here is a very rough first hack (for discussion/testing purposes only!): A second hack, slightly less rough hack: Index: ssl_private.h =================================================================== --- ssl_private.h (revision 832979) +++ ssl_private.h (working copy) @@ -335,6 +335,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; @@ -618,7 +632,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 Index: ssl_engine_init.c =================================================================== --- ssl_engine_init.c (revision 832979) +++ ssl_engine_init.c (working copy) @@ -520,10 +520,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, Index: ssl_engine_io.c =================================================================== --- ssl_engine_io.c (revision 832979) +++ ssl_engine_io.c (working copy) @@ -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) @@ -476,6 +483,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; + } + /* In theory, OpenSSL should flush as necessary, but it is known * not to do so correctly in some cases; see PR 46952. * @@ -1699,6 +1712,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, r, c); Index: ssl_engine_kernel.c =================================================================== --- ssl_engine_kernel.c (revision 832979) +++ ssl_engine_kernel.c (working copy) @@ -733,6 +733,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); @@ -754,6 +758,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: " @@ -1814,76 +1820,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, server_rec *s, + conn_rec *c, int where, int rc) { - conn_rec *c; - server_rec *s; - SSLSrvConfigRec *sc; - /* - * find corresponding server + * create the various trace messages */ - if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { - return; + if (where & SSL_CB_HANDSHAKE_START) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "%s: Handshake: start", SSL_LIBRARY_NAME); } - - s = mySrvFromConn(c); - if (!(sc = mySrvConfig(s))) { - return; + else if (where & SSL_CB_HANDSHAKE_DONE) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "%s: Handshake: done", SSL_LIBRARY_NAME); } - - /* - * create the various trace messages - */ - if (s->loglevel >= APLOG_DEBUG) { - if (where & SSL_CB_HANDSHAKE_START) { + 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: 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", + "%s: Exit: failed in %s", SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } - else if (where & SSL_CB_READ) { + else if (rc < 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Read: %s", + "%s: Exit: error in %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: 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)); - } - } } /* @@ -1903,6 +1888,60 @@ } } +/* + * 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; + SSLSrvConfigRec *sc; + SSLConnRec *scr; + + /* + * find corresponding server + */ + if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { + return; + } + + scr = myConnConfig(c); + if (!scr) { + 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 (!(sc = mySrvConfig(s))) { + return; + } + + if (s->loglevel >= APLOG_DEBUG) { + log_tracing_state(ssl, s, c, where, rc); + } +} + #ifndef OPENSSL_NO_TLSEXT /* * This callback function is executed when OpenSSL encounters an extended ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLJoe Orton wrote:
> On Fri, Nov 06, 2009 at 12:00:06AM +0000, Joe Orton wrote: >> Here is a very rough first hack (for discussion/testing purposes only!): > > A second hack, slightly less rough hack: Lovely - and that works exactly as I'd expect; and does also 'dro' the connection with the openssl s_client 'R' re-negotiate forcing as well. So I guess the one thing we need now is to double check with the OpenSSL folks if the basic concept of this patch covers all basis. I.e. really sees every possible renegotiate - regardless of what or from where initiated. I am a bit worried that OpenSSL may have to clean an abstraction layer perhaps. To recap (and verify my understanding - we register an info callback and then track the connection stat: + SSL_CTX_set_info_callback(ctx, ssl_callback_Info); ... +void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) + /* 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; + } And we then check this state on every read/write in the bio read/write callbacks: static int bio_filter_out_write/read(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; + } So it owuld be useful to have confirmed from the OpenSSL experts that this gives is visibility of each and every stage change. And then we're good. Dw. Index: ssl_private.h =================================================================== --- ssl_private.h (revision 832979) +++ ssl_private.h (working copy) @@ -335,6 +335,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; @@ -618,7 +632,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 Index: ssl_engine_init.c =================================================================== --- ssl_engine_init.c (revision 832979) +++ ssl_engine_init.c (working copy) @@ -520,10 +520,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, Index: ssl_engine_io.c =================================================================== --- ssl_engine_io.c (revision 832979) +++ ssl_engine_io.c (working copy) @@ -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) @@ -476,6 +483,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; + } + /* In theory, OpenSSL should flush as necessary, but it is known * not to do so correctly in some cases; see PR 46952. * @@ -1699,6 +1712,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, r, c); Index: ssl_engine_kernel.c =================================================================== --- ssl_engine_kernel.c (revision 832979) +++ ssl_engine_kernel.c (working copy) @@ -733,6 +733,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); @@ -754,6 +758,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: " @@ -1814,76 +1820,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, server_rec *s, + conn_rec *c, int where, int rc) { - conn_rec *c; - server_rec *s; - SSLSrvConfigRec *sc; - /* - * find corresponding server + * create the various trace messages */ - if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { - return; + if (where & SSL_CB_HANDSHAKE_START) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "%s: Handshake: start", SSL_LIBRARY_NAME); } - - s = mySrvFromConn(c); - if (!(sc = mySrvConfig(s))) { - return; + else if (where & SSL_CB_HANDSHAKE_DONE) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "%s: Handshake: done", SSL_LIBRARY_NAME); } - - /* - * create the various trace messages - */ - if (s->loglevel >= APLOG_DEBUG) { - if (where & SSL_CB_HANDSHAKE_START) { + 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: 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", + "%s: Exit: failed in %s", SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } - else if (where & SSL_CB_READ) { + else if (rc < 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Read: %s", + "%s: Exit: error in %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: 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)); - } - } } /* @@ -1903,6 +1888,60 @@ } } +/* + * 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; + SSLSrvConfigRec *sc; + SSLConnRec *scr; + + /* + * find corresponding server + */ + if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { + return; + } + + scr = myConnConfig(c); + if (!scr) { + 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 (!(sc = mySrvConfig(s))) { + return; + } + + if (s->loglevel >= APLOG_DEBUG) { + log_tracing_state(ssl, s, c, where, rc); + } +} + #ifndef OPENSSL_NO_TLSEXT /* * This callback function is executed when OpenSSL encounters an extended ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLJoe Orton wrote:
> On Fri, Nov 06, 2009 at 12:00:06AM +0000, Joe Orton wrote: >> Here is a very rough first hack (for discussion/testing >> purposes only!): > > A second hack, slightly less rough hack: Lovely - and that works exactly as I'd expect; and does also 'drop' the connection with the openssl s_client 'R' re-negotiate forcing as well. So I guess the one thing we need now is to double check with the OpenSSL folks if the basic concept of this patch covers all bases. I.e. really sees every possible renegotiate - regardless of what or from where initiated. I am a bit worried that OpenSSL may have to clean an abstraction layer perhaps. To recap (and verify my understanding - we register an info callback and then track the connection stat: + SSL_CTX_set_info_callback(ctx, ssl_callback_Info); ... +void ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE ssl, int where, int rc) + /* 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; + } And we then check this state on every read/write in the bio read/write callbacks: static int bio_filter_out_write/read(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; + } So it owuld be useful to have confirmed from the OpenSSL experts that this gives is visibility of each and every stage change. And then we're good. Dw. Index: ssl_private.h =================================================================== --- ssl_private.h (revision 832979) +++ ssl_private.h (working copy) @@ -335,6 +335,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; @@ -618,7 +632,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 Index: ssl_engine_init.c =================================================================== --- ssl_engine_init.c (revision 832979) +++ ssl_engine_init.c (working copy) @@ -520,10 +520,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, Index: ssl_engine_io.c =================================================================== --- ssl_engine_io.c (revision 832979) +++ ssl_engine_io.c (working copy) @@ -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) @@ -476,6 +483,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; + } + /* In theory, OpenSSL should flush as necessary, but it is known * not to do so correctly in some cases; see PR 46952. * @@ -1699,6 +1712,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, r, c); Index: ssl_engine_kernel.c =================================================================== --- ssl_engine_kernel.c (revision 832979) +++ ssl_engine_kernel.c (working copy) @@ -733,6 +733,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); @@ -754,6 +758,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: " @@ -1814,76 +1820,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, server_rec *s, + conn_rec *c, int where, int rc) { - conn_rec *c; - server_rec *s; - SSLSrvConfigRec *sc; - /* - * find corresponding server + * create the various trace messages */ - if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { - return; + if (where & SSL_CB_HANDSHAKE_START) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "%s: Handshake: start", SSL_LIBRARY_NAME); } - - s = mySrvFromConn(c); - if (!(sc = mySrvConfig(s))) { - return; + else if (where & SSL_CB_HANDSHAKE_DONE) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "%s: Handshake: done", SSL_LIBRARY_NAME); } - - /* - * create the various trace messages - */ - if (s->loglevel >= APLOG_DEBUG) { - if (where & SSL_CB_HANDSHAKE_START) { + 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: 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", + "%s: Exit: failed in %s", SSL_LIBRARY_NAME, SSL_state_string_long(ssl)); } - else if (where & SSL_CB_READ) { + else if (rc < 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "%s: Read: %s", + "%s: Exit: error in %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: 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)); - } - } } /* @@ -1903,6 +1888,60 @@ } } +/* + * 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; + SSLSrvConfigRec *sc; + SSLConnRec *scr; + + /* + * find corresponding server + */ + if (!(c = (conn_rec *)SSL_get_app_data((SSL *)ssl))) { + return; + } + + scr = myConnConfig(c); + if (!scr) { + 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 (!(sc = mySrvConfig(s))) { + return; + } + + if (s->loglevel >= APLOG_DEBUG) { + log_tracing_state(ssl, s, c, where, rc); + } +} + #ifndef OPENSSL_NO_TLSEXT /* * This callback function is executed when OpenSSL encounters an extended ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
|
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLDirk-Willem van Gulik wrote:
> > So I guess the one thing we need now is to double check with the OpenSSL > folks if the basic concept of this patch covers all basis. I.e. really > sees every possible renegotiate - regardless of what or from where > initiated. I am a bit worried that OpenSSL may have to clean an > abstraction layer perhaps. > I can only comment about *this* OpenSSL folk ;-) I only found out about this issue yesterday and I'm on vacation until early next week so I've only been following this in outline. The normal session resumption can be performed using s_client and the -sess_out and -sess_in options so check that works normally if you haven't already. That should be checked with -no_ticket too to check stateful resumption (stateless is default for newer versions of OpenSSL). Steve. -- Dr Stephen N. Henson. Senior Technical/Cryptography Advisor, Open Source Software Institute: www.oss-institute.org OpenSSL Core team: www.openssl.org ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLSo what are the next steps here ?
- Joe's patch is final. - Give the community the advice 'immediately' - with a website update and an email to announce: Apache httpd is affected by CVE-XXXX (The SSL Injectin or MiM attack). We strongly urge you to upgrade to OpenSSL 0.9.8l; and be prepared to deploy 0.9.8m as it becomes available. For those who are not able to upgrade swiftly and/or for those who need detailed logging - we recommend that you roll out this patch (URL) as soon as possible. If you are unable to patch and unable to roll our a newer version of OpenSSL then we recommend that you ensure that you limit your configuratin to a single 'SSLClient require' or 'SSLClient none' at VirtualHost/Sever level and remove all other (re)negotiation changes. However this does NOT fully protect you - it just curtails authentication. A version with this patch, Apache 2.2.15, is currently beeing readied; there are no plans for a backport to 1.3.X at this time. - Check how much we have on the roster in - and either release a 2.x with just this CVE - or a more wrapped up one ? Do we need to backport this for the 1.3.42 branch ? Thanks, Dw. ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn 11/06/2009 10:58 PM, Dirk-Willem van Gulik wrote: > So what are the next steps here ? > > - Joe's patch is final. > > - Give the community the advice 'immediately' - with a website > update and an email to announce: > > Apache httpd is affected by CVE-XXXX (The SSL Injectin > or MiM attack). > > We strongly urge you to upgrade to OpenSSL 0.9.8l; and be > prepared to deploy 0.9.8m as it becomes available. > > For those who are not able to upgrade swiftly and/or for those > who need detailed logging - we recommend that you roll out > this patch (URL) as soon as possible. I guess no one who needs server triggered renegotiation in its configuration can upgrade to 0.9.8l as to my understanding *all* renegotiations are simply turned off in 0.9.8l. So these people can only go with our patch or a fresh release of httpd and are still *vulnerable* in those URL spaces that are somehow "protected" by these renegotiations. I guess how much in the cert case also depends on the clients browser settings and its user (does it send a certificate even though the original request by the browser did not request one?) > If you are unable to patch and unable to roll our a newer > version of OpenSSL then we recommend that you ensure that > you limit your configuratin to a single 'SSLClient require' > or 'SSLClient none' at VirtualHost/Sever level and remove > all other (re)negotiation changes. However this does NOT > fully protect you - it just curtails authentication. > > A version with this patch, Apache 2.2.15, is currently > beeing readied; there are no plans for a backport to > 1.3.X at this time. > > - Check how much we have on the roster in - and either release > a 2.x with just this CVE - or a more wrapped up one ? > > Do we need to backport this for the 1.3.42 branch ? Note that mod_ssl is not part of 1.3.x but a separate project. So only 2.0.x might be worth a thought. Regards Rüdiger ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLJoe Orton wrote:
> On Fri, Nov 06, 2009 at 12:00:06AM +0000, Joe Orton wrote: >> > On Thu, Nov 05, 2009 at 09:31:00PM +0000, Joe Orton wrote: >>> > > * we can detect in mod_ssl when the client is renegotiating by using the >>> > > callback installed using SSL_CTX_set_info_callback(), in conjunction >>> > > with suitable flags in the SSLConnRec to detect the cases where this is >>> > > either a server-initiated renegotiation or the initial handshake on the >>> > > connection. >> > >> > Here is a very rough first hack (for discussion/testing purposes only!): > A second hack, slightly less rough hack: Joe, instead of hard coding this, a very nice solution would be to have a new directive "SSLServerRenegociation Allow" or even more flexible "SSLRenegociation disabled/serveronly/enabled" with disabled as default value. This would allow sites that need server renegotiation to make it quite more secure, by using a strategy similar to what is suggested here : https://issues.apache.org/bugzilla/show_bug.cgi?id=39243#c7 "The obvious answer for an 'upload' style operation is to ensure they never hit your upload page without going through a simpler front page which first enforces the renegotation. This can be your upload form page." So the server would first direct the user to a "SSLRenegociation serveronly" page that is conceived so that request to it can not be abused, and use "SSLRenegociation enabled" for all unsafe locations, the user accessing them only when his connection has already been upgraded to use client certs (this is similar to what Peter suggested already). The only weak point in that solution is that Apache seems to require renegotiation in quite a few case where it should not be really necessary. But as any case of Apache requiring renegotiation will break anyone using the more radical option of fully disabling renegotiation I'll open a separate message for this. ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
|
|
Re: TLS renegotiation attack, mod_ssl and OpenSSLOn Tue, Nov 10, 2009 at 03:19:39PM +0100, Jean-Marc Desperrier wrote:
> Joe Orton wrote: >> On Fri, Nov 06, 2009 at 12:00:06AM +0000, Joe Orton wrote: >>> > On Thu, Nov 05, 2009 at 09:31:00PM +0000, Joe Orton wrote: >>>> > > * we can detect in mod_ssl when the client is renegotiating by using the >>>> > > callback installed using SSL_CTX_set_info_callback(), in conjunction >>>> > > with suitable flags in the SSLConnRec to detect the cases where this is >>>> > > either a server-initiated renegotiation or the initial handshake on the >>>> > > connection. >>> > >>> > Here is a very rough first hack (for discussion/testing purposes only!): >> A second hack, slightly less rough hack: > > Joe, instead of hard coding this, a very nice solution would be to have > a new directive "SSLServerRenegociation Allow" or even more flexible > "SSLRenegociation disabled/serveronly/enabled" with disabled as default > value. Yes, sure. What is possible in mod_ssl will depend on what interfaces OpenSSL will expose for this, which is not yet clear. Regards, Joe ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@... Automated List Manager majordomo@... |
| Free embeddable forum powered by Nabble | Forum Help |