Skip to content

Instantly share code, notes, and snippets.

@t-j-h
Created April 27, 2014 04:12
Show Gist options
  • Save t-j-h/11337380 to your computer and use it in GitHub Desktop.
Save t-j-h/11337380 to your computer and use it in GitHub Desktop.
block the heartbeat usage in application code
/* heartbeat_block.c - block the heartbeat usage in application code if
* unsure if you are working with a patched or non-patched
* library or if you want to log the exploit attempts
*/
/* include defines to make code more readable without pulling in
* any "internal" OpenSSL header files
*/
#ifndef TLS1_RT_HEARTBEAT
#define TLS1_RT_HEARTBEAT 24
#endif /* TLS1_RT_HEARTBEAT */
#ifndef TLS1_HB_REQUEST
#define TLS1_HB_REQUEST 1
#endif /* TLS1_HB_REQUEST */
#ifndef TLS1_HB_RESPONSE
#define TLS1_HB_RESPONSE 2
#endif /* TLS1_HB_RESPONSE */
#ifndef n2s
#define n2s(c,s) ((s=(((unsigned int)(c[0]))<< 8)| \
(((unsigned int)(c[1])) )),c+=2)
#endif /* n2s */
#ifndef s2n
#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
c[1]=(unsigned char)(((s) )&0xff)),c+=2)
#endif /* s2n */
static void msg_cb_hb_block(int write_p, int version,
int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
{
unsigned char *p=(unsigned char *)buf;
unsigned short hbtype=0;
unsigned int payload=0;
BIO *null_bio=NULL;
if (content_type==TLS1_RT_HEARTBEAT) {
if (len>=3) {
hbtype = *p++;
n2s(p,payload);
/* if a heartbeat request is requesting a payload larger than the
* record size it is an attempt to expolit CVE-2014-0160 and we
* force-drop the connection
*/
if (3+payload+16>len) {
/* remove the I/O layer out from underneath the SSL layer so we
* can be sure no processing makes it out
*/
/* it would be great if we could just set the BIOs to null as
* but unfortunately some OpenSSL internal code assumes the BIO
* is always there ...
*/
/*
(void)SSL_set_bio(ssl,NULL,NULL);
*/
null_bio=BIO_new(BIO_f_null());
(void)SSL_set_bio(ssl,null_bio,null_bio);
(void)SSL_set_quiet_shutdown(ssl,1);
(void)SSL_shutdown(ssl);
/* do whatever you want to indicate to the caller the reason
* why the connection has been blocked ... can use the 'arg'
* value to reach back to whatever was set against the SSL_CTX
* or the SSL as the msg_callback_arg - in this simple example
* just print out a notice - applications will do something more
* interesting to report to the user
*/
fprintf(stderr,"msg_cb_hb_block: blocked heartbeat attempt\n");
}
}
}
done: ;
}
#ifdef PUT_THIS_IN_THE_APPLICATION
/* note: change user_context to NULL if you do not have one to use */
/* if using an SSL_CTX level interface to hook this in */
(void)SSL_CTX_set_msg_callback(sctx,msg_cb_hb_block);
(void)SSL_CTX_set_msg_callback_arg(sctx,(void *)user_context);
/* if using an SSL level hook ... at which point you can track per
* connection information
*/
(void)SSL_set_msg_callback(ssl,msg_cb_hb_block);
(void)SSL_set_msg_callback_arg(ssl,(void *)user_context);
#endif /* PUT_THIS_IN_THE_APPLICATION */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment