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.
libssl-dev package
When compiling Nmap you need the libssl-dev
package installed. Nmap nse scripts such as ssl-cert will not work without it.
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.
Testing the SSL cert parse script
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
Python script
Once the scan has completed, the python script below can be used to parse the Nmap XML and produce the csv
output. The results can be loaded into a spreadsheet, or parsed further, 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,,,,,
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.
Parse XML data
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
Nmap XML to CSV
Not specifically tied to the SSL results; we have another script that converts Nmap XML to CSV. This is an easy to use script that can be adapted to achieve the output needed for reporting.
Different organisations have different reporting requirements so this simple script was created to enable anyone to modify it as required with minimal python
knowledge.
https://github.com/hackertarget/nmap-csv-xlsx