Heartbleed
The OpenSSL heartbleed vulnerability CVE-2014-0160 has been all over the news this month. I posted an overview on what to do and how to detect exploit attempts.
Certificate revocations
Generating new certificates is one of the advices to cope with this vulnerability. A new certificate means that you have to revoke the old one. Revoked certificates are ‘announced’ in a CRL, or a certificate revocation list.
Graphing CRL content
SANS ISC has a graph on certificates revoked per day. This graph is based on different sources. I am only interested in the CRL revocation data of Terena. Below are the graphs for the Terena CRL list. It is generated with a Python script (see below).
You can see a spike shortly after the announcement of the Heartbleed bug but I would have expected to see a higher number of requested revoked certificates.
Script to generate stats
The Python script generates a JSON file that is used to feed a Google Chart. It uses a file TERENASSLCA.crl.parsed that is the output of parsing the CRL file through OpenSSL.
wget --output-document TERENASSLCA.crl http://crl.tcs.terena.org/TERENASSLCA.crl openssl crl -in TERENASSLCA.crl -inform DER -text > TERENASSLCA.crl.parsed
#!/usr/bin/python # # Koen Van Impe - Google Chart graphs based on Terena CRL # # In cron: # wget http://crl.tcs.terena.org/TERENASSLCA.crl # openssl crl -in TERENASSLCA.crl -inform DER -text > TERENASSLCA.crl.parsed # crl = open('TERENASSLCA.crl.parsed', 'r') crl_json = open('terena-crl.json', 'w') revoc_match = 'Revocation Date:' revoc_date = 'Last Update:' crl_data = {} update_date = 'Unknown' # Init dictionary for x in range(1, 31): crl_data[ x ] = 0 # Walk through CRL file for line in crl: pos = line.find( revoc_match ) pos_update = line.find( revoc_date ) if pos > 0 : # A line indicating a revoked certificate? date = line[(pos + len( revoc_match )):].strip().split(' ') # Only grab the Apr2014 (could also add an extra 'match' above) if date[0] == 'Apr' and date[3] == '2014': day = int(date[1]) crl_data[ day ] = crl_data[ day ] + 1 elif pos_update > 0: update_date = line[(pos_update + len( revoc_date )):].strip() # Build JSON crl_json.write( '{"update_date": "' + update_date + '", \n "googlechart": ') crl_json.write( '{"cols":[{"type":"string"},{"type":"number","label":"hits"}] \n') crl_json.write( ', "rows":[ \n') row = 1 for item in crl_data: json_line = '{"c":[{"v":"' + str(item) + '/Apr"},{"v":"' + str(crl_data[ item ]) + '"}]} ' if row != len(crl_data): json_line = json_line + " , " crl_json.write ( json_line + "\n") row = row + 1 crl_json.write( ']} }\n') # Cleanup crl.close() crl_json.close()
How did you make the graphs?
I fetch the CRL; parse it with OpenSSL and then the python script parses it to create a JSON file. The graph (+table) itself is made with Google Chart.