Re: [exim-dev] heartbleed detection

Top Page
Delete this message
Reply to this message
Author: Wolfgang Breyha
Date:  
To: exim-dev, Phil Pennock
Subject: Re: [exim-dev] heartbleed detection
On 09/04/14 23:36, Phil Pennock wrote:
> Note that to have a detection feature of "someone tried it", we'd
> probably also want support in GnuTLS to detect the attack probes. But
> otherwise, I'm happy with this as an EXPERIMENTAL_HEARTBLEED_DETECT
> feature, as long as we're clear that the goal is to remove it down the
> line, instead of integrate it. I also think that you'll get a lot of
> noise in the logs, akin unto web-server logs recording people searching
> for exploitable PHP scripts.


The main reason I did the patch (and especially the attached improved
patch) was to get an idea how often the exploit is triggered and what
actually happens if somebody exploits that with exim (or other daemons like
cyrus). Most requests will come from myself to get samples;-)

My new patch writes the "64k buffer" a vulnerable OpenSSL would leak to the
attacker to /var/tmp/exim-heartbleeds/hb-<pid>. OpenSSL provides the
pointer to exactly the exploited memory to the callback function. Nothing
changed in that part of the code. And it seems accessible for the exactly
same odd reasons without SEGV as mentioned here:
http://article.gmane.org/gmane.os.openbsd.misc/211963

The idea is to get samples of what OpenSSL would leak out of exim to
analyze that without being vulnerable. Write protecting the directory
prevents writing of new samples. Directory has to be writable by the user
exim is actually running as anyway.

I think that exim is a bit different to apache or cyrus since it is not
preforked and reused for many sessions of different users. Most likely no
passwords of other users from AUTH, but still the private key is at high
risk. Searching for it in samples sounded interesting enough.

I'm not sure if it makes any sense to include that even as EXPERIMENTAL. I
provided it mostly for people interested in debugging heartbleed and able
to patch short lived interim versions. The code is easily ported to other
daemons like cyrus which use OpenSSL in very similar ways.

Currently I think I'll remove the code as soon as aftermath is done.

> Probably of most use for Universities who want to be able to have
> someone in Security knock on a student's door to have a quiet discussion
> about wise decisions and their future.


There are so many test scripts and sites out there currently. I can't blame
any of our users or CERT guys for testing our systems.

> Probably best to just deploy a fixed OpenSSL and verify that running
> "exim -d --version" shows the new OpenSSL Runtime version.


Deploying a fixed OpenSSL was the very very first step;-) Usually I check
with lsof which pids are still using already deleted libraries. In our case
"exim -d --version" shows the exactly same version since I only added the
patch to the .spec file.

Greetings, Wolfgang
--
Wolfgang Breyha <wbreyha@???> | http://www.blafasel.at/
Vienna University Computer Center | Austria
--- src/tls-openssl.c.prehb    2014-04-09 13:16:19.000000000 +0200
+++ src/tls-openssl.c    2014-04-09 23:33:06.000000000 +0200
@@ -330,6 +330,42 @@
 return verify_callback(state, x509ctx, &tls_in, &server_verify_callback_called, &server_verify_optional);
 }


+void tls_msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
+{
+    if (content_type == TLS1_RT_HEARTBEAT)
+    {
+        if (len >= 3)
+        {
+            unsigned short hbtype;
+            unsigned int payll;
+            const unsigned char *p = buf;
+            hbtype = *p++;
+            payll = (((unsigned int)(*p++))<< 8)|(((unsigned int)(*p++)));
+            if (hbtype == TLS1_HB_REQUEST)
+                if (payll > len - 3)
+                {
+                    /* write max payload size of 0xFFFF to file first */
+                    /* syslogging first shows up in TLS hb buffer otherwise. WTF? */ 
+                    char fname[1024];
+                    snprintf(fname, sizeof(fname), "/var/tmp/exim-heartbleed/hb-%lu", (unsigned long) getpid());
+                    int fd =  -1;
+                    fd = open(fname, O_CREAT | O_APPEND | O_WRONLY, 0644);
+
+                    if (fd != -1)
+                    {
+                        write(fd, buf, 65535);
+                        close(fd);
+                    }
+
+                    DEBUG(D_tls) debug_printf("TLS heartbleed attack detected: %d < %d\n", len - 3, payll);
+                        log_write(0, LOG_MAIN|LOG_PANIC,
+                          "TLS heartbleed attack detected: %d < %d", len - 3, payll);
+                } else {
+                    DEBUG(D_tls) debug_printf("TLS valid heartbeat req received\n");
+                }
+        }
+    }
+}



/*************************************************
@@ -1160,6 +1196,8 @@

SSL_CTX_set_tmp_rsa_callback(*ctxp, rsa_callback);

+SSL_CTX_set_msg_callback(*ctxp, tls_msg_cb);
+
/* Finally, set the timeout, and we are done */

SSL_CTX_set_timeout(*ctxp, ssl_session_timeout);