Parse Nmap XML to get SSL Certificate details

Extract SSL certificate details from a range of IP addresses using Nmap XML and a simple python script. The python script parses the Nmap XML output from the ssl-cert.nse script and produces csv output with the target SSL certificate details.

When compiling Nmap you will need to have the libssl-dev package installed as Nmap nse scripts such as ssl-cert will not work without it being installed. Once this is installed ./configure, make, make install to install the latest version of Nmap.

apt-get install libssl-dev

Once the package is installed go ahead and install Nmap from source. Extract the source into a folder, configure and install.

For a quick test of the SSL cert parse script I grabbed the top 25 computing sites from Alexa. Start Nmap with the ssl-cert nse script. The -iL option loads the list 25 target host names with the -oX producing the Nmap XML results.

nmap -iL top25-tech.txt -sV -p 443 -oX nmap-results-top25 --script=ssl-cert

Once the scan has completed the python script below can be used parse the Nmap XML and produce the csv output. The results can then be loaded into a spreadsheet, or parsed further to depending on your needs.

testuser@ubuntu:~$ python nmap-ssl-certs.py nmap-results-top25.xml
 
150.101.195.240,www.google.com,Google Inc,US,2014-05-07,2014-08-05
31.13.70.17,*.facebook.com,Facebook, Inc.,US,2014-02-28,2015-04-13
150.101.195.212,*.google.com,Google Inc,US,2014-05-07,2014-08-05
74.125.237.149,mail.google.com,Google Inc,US,2014-05-07,2014-08-05
98.139.183.24,www.yahoo.com,Yahoo Inc.,US,2014-04-09,2015-04-09
198.35.26.96,*.wikipedia.org,Wikimedia Foundation, Inc.,US,2012-10-21,2016-01-20
199.59.148.82,twitter.com,Twitter, Inc.,US,2014-04-08,2016-05-09
216.52.242.80,www.linkedin.com,LinkedIn Corporation,US,2013-12-19,2016-12-30
98.136.189.41,*.login.yahoo.com,Yahoo Inc.,US,2014-04-08,2015-04-09
65.55.143.19,mail.live.com,Microsoft Corporation,US,2013-05-21,2015-05-22
150.101.195.216,*.google.com,Google Inc,US,2014-05-07,2014-08-05
150.101.195.227,*.google.com,Google Inc,US,2014-05-07,2014-08-05
119.160.243.163,search.yahoo.com,Yahoo Inc.,US,2014-04-08,2015-04-09
192.0.82.252,wordpress.com,Automattic, Inc.,US,2014-04-16,2016-04-16
204.79.197.200,*.bing.com,Microsoft Corporation,US,2014-05-20,2016-05-19
54.225.139.43,*.pinterest.com,Pinterest Inc,US,2014-04-09,2017-04-13
66.235.120.127,,,,,
150.101.195.249,*.google.com,Google Inc,US,2014-05-07,2014-08-05
65.55.206.228,,,,,
66.211.169.66,paypal.com,PayPal, Inc.,US,2013-01-09,2015-01-11
134.170.188.221,microsoft.com,,,2013-06-20,2015-06-20
17.172.224.47,apple.com,Apple Inc.,US,2012-11-13,2014-11-03
23.23.110.81,*.imgur.com,Imgur, Inc.,US,2013-06-25,2016-08-31
198.252.206.140,*.stackexchange.com,Stack Exchange, Inc.,US,2013-07-02,2016-07-06
68.71.220.3,,,,,

Here is the python script. The script is simple but it works, it should be pretty easy to read allowing modification to parse other NSE scripts and results from the Nmap XML output. There are many ways to parse XML data, the xml.dom method used here seems to be one of the more straightforward for parsing the Nmap XML. Another option could include using ElementTree, or even using xmlstarlet in bash as seen on this stack.exchange post.

#!/usr/bin/env python
import xml.dom.minidom
import sys
import getopt
try: 
    scandata = sys.argv[1]
except:
    print "*** You need to supply an Nmap XML file ***"
if scandata:
    doc = xml.dom.minidom.parse(scandata)
    output = []
    for host in doc.getElementsByTagName("host"):
        ip = ''
        commonName = ''
        organizationName = ''
        countryName = ''
        notBefore = ''
        notAfter = ''
        addresses = host.getElementsByTagName("address")
        ip = addresses[0].getAttribute("addr")                         # Get IP address from addr element 
        scripts = host.getElementsByTagName("script")
        for script in scripts:
              for elem in script.getElementsByTagName("elem"):         # Get cert details for each target 
                 try:
                    if elem.getAttribute("key") == 'commonName':
                       if commonName == '':                            # Only get the first commonName 
                           commonName =  elem.childNodes[0].nodeValue
                 except:
                    pass
                 try:
                    if elem.getAttribute("key") == 'organizationName':
                       if organizationName == '': 
                           organizationName =  elem.childNodes[0].nodeValue
                 except:
                    pass
                 try:
                    if elem.getAttribute("key") == 'countryName':
                       countryName =  elem.childNodes[0].nodeValue
                 except:
                    pass
                 try:
                    if elem.getAttribute("key") == 'notBefore':
                       notBefore =  elem.childNodes[0].nodeValue
                       notBefore = notBefore.split('T')[0]
                 except:
                    pass
                 try:
                    if elem.getAttribute("key") == 'notAfter':
                       notAfter =  elem.childNodes[0].nodeValue
                       notAfter = notAfter.split('T')[0]
                 except:
                    pass
        output.append(ip + ',' + commonName + ',' + organizationName + ',' + countryName + ',' + notBefore + ',' + notAfter)
    for i in output:
        print i
Wait. There's more. Additional Nmap resources and tips are just a click away or check out the hosted vulnerability scanners
Share this Post
Share on FacebookTweet about this on TwitterShare on Google+Share on StumbleUpon

, ,