Welcome! Log In Create A New Profile

Advanced

Re: [PATCH] Disable SSL renegotiation (CVE-2009-3555).

Maxim Dounin
November 08, 2009 08:54PM
Hello!

On Sat, Nov 07, 2009 at 06:23:15PM +0300, Maxim Dounin wrote:

> On Fri, Nov 06, 2009 at 04:22:03PM +0300, Maxim Dounin wrote:
>
> > Here is proof-of-concept patch which disables ssl renegotiation
> > which was recently found vulnerable to man-in-the-middle attacks.
> >
> > I've tested it with old openssl (0.9.7e) and most recent one
> > (0.9.8l, with renegotiation disabled out of the box) and it
> > appears to work as expected.
>
> Updated patch which takes care of openssl problems with disabled
> renegotiation (present even in most recent 0.9.8l) and closes
> connection as soon as we detect renegotiation attempt.
>
> > Further testing much appreciated.
>
> Still applies.
>
> Some notes:
>
> 1. Patch is for 0.8.22, but it applies to 0.7.63 cleanly;
>
> 2. If you see "[alert] ... unexpected SSL renegotiation" in logs
> and it appears to happen on legitimate use - please report.
>
> 3. Patch disables all renegotiations out there, including ones
> with backends. This may hurt setups with backends requesting for
> client certs via renegotiation (e.g. apache known to be able to do
> so when configured). AFAIK currently there is no way to fix such
> setups to make them secure.

Updated patch. It disables renegotiation only for server
connections (ones accepted by nginx). This will preserve
configurations mentioned in (3) as there is no reason to broke
them (nginx doesn't check backend certificates anyway).

Maxim Dounin
# HG changeset patch
# User Maxim Dounin <mdounin@mdounin.ru>
# Date 1257729930 -10800
# Node ID 265dac987a843ad2538275fdea16c7a14457194b
# Parent 8da5668048b423cb58a77b9d496956e9cad96709
Disable SSL renegotiation (CVE-2009-3555).

It was recently discovered that SSL and TLS are vulnerable to
man-in-the-middle attacks due to renegotiation feature (see
http://extendedsubset.com/?p=8).

Most recent version of openssl (0.9.8l) disables renegotiation unless
explicitly enabled by application (not recommended though). Since nginx
doesn't require renegotiation to work - try to disable it for older
openssl versions too.

Note that openssl (up to most recent 0.9.8l) doesn't handle disabled
renegotiation gracefully (i.e. goes to an unconsistent state when client
asks for renegotiation instead of sending back NO_RENEGOTIATION alert)
and we have to explicitly drop connection if we detect renegotiation
attempt.

diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -15,6 +15,8 @@ typedef struct {


static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
+static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
+ int ret);
static void ngx_ssl_handshake_handler(ngx_event_t *ev);
static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
static void ngx_ssl_write_handler(ngx_event_t *wev);
@@ -175,6 +177,8 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_

SSL_CTX_set_read_ahead(ssl->ctx, 1);

+ SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
+
return NGX_OK;
}

@@ -349,6 +353,30 @@ ngx_http_ssl_verify_callback(int ok, X50
return 1;
}

+static void
+ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
+{
+ ngx_connection_t *c;
+
+ if (where & SSL_CB_HANDSHAKE_START && ssl_conn->server) {
+ c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
+
+ if (c->ssl->handshaked) {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+ "unexpected SSL renegotiation detected");
+
+ c->ssl->renegotiation = 1;
+
+ /*
+ * rearm disable flag as openssl (as of 0.9.8l at least) loses
+ * it due to bug; this doesn't really matter since we will close
+ * this connection anyway, but just to be sure
+ */
+
+ c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+ }
+ }
+}

ngx_int_t
ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
@@ -587,6 +615,12 @@ ngx_ssl_handshake(ngx_connection_t *c)
c->recv_chain = ngx_ssl_recv_chain;
c->send_chain = ngx_ssl_send_chain;

+ /* initial handshake done, disable renegotiation (CVE-2009-3555) */
+
+ if (c->ssl->connection->server) {
+ c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+ }
+
return NGX_OK;
}

@@ -789,6 +823,21 @@ ngx_ssl_handle_recv(ngx_connection_t *c,
int sslerr;
ngx_err_t err;

+ if (c->ssl->renegotiation) {
+ /*
+ * openssl (at least up to 0.9.8l) doesn't handle disabled
+ * renegotiation gracefully, so drop connection here
+ */
+
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "unexpected SSL renegotiation");
+
+ c->ssl->no_wait_shutdown = 1;
+ c->ssl->no_send_shutdown = 1;
+
+ return NGX_ERROR;
+ }
+
if (n > 0) {

if (c->ssl->saved_write_handler) {
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -41,6 +41,7 @@ typedef struct {
ngx_event_handler_pt saved_write_handler;

unsigned handshaked:1;
+ unsigned renegotiation:1;
unsigned buffer:1;
unsigned no_wait_shutdown:1;
unsigned no_send_shutdown:1;
Subject Author Posted

[PATCH] Disable SSL renegotiation (CVE-2009-3555).

Maxim Dounin November 06, 2009 08:26AM

Re: [PATCH] Disable SSL renegotiation (CVE-2009-3555).

Maxim Dounin November 07, 2009 10:34AM

Re: [PATCH] Disable SSL renegotiation (CVE-2009-3555).

Maxim Dounin November 08, 2009 08:54PM

Re: [PATCH] Disable SSL renegotiation (CVE-2009-3555).

Maxim Dounin November 09, 2009 02:04PM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 76
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready