Skip to content

Instantly share code, notes, and snippets.

@thesubtlety
Last active October 1, 2022 10:17
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thesubtlety/f222bf5910e58785b9df2b22081c82c9 to your computer and use it in GitHub Desktop.
Save thesubtlety/f222bf5910e58785b9df2b22081c82c9 to your computer and use it in GitHub Desktop.
Parse Shodan data file and extract CVE details by host, writing to CSV file
#!/usr/bin/env python3
import os
import re
import sys
import json
import gzip
import csv
import datetime
import shodan
'''
Parses shodan files and pulls out CVE details by host
"IP CVE Verified CVSS Summary References"
And writes to new csv file
0. pip install shodan
1. Assuming shodan data files have been obtained
2. python3 parse-shodan-cve-data.py <directory>
'''
csv_out = []
def parse_shodan_file(fname):
if fname.split(".")[-1] == "gz":
data = gzip.open(fname, 'r').read().decode('utf-8').strip()
data = data.split('\n')
else:
with open(fname,'r') as f:
data = [e for e in f if e.strip()]
#print("\n" + "-" * 30)
#print("File: %s" % fname)
#print("Data: ", data[0][0:100])
for e in data:
e = json.loads(e)
ip = e['ip_str']
if 'vulns' in e and e['vulns'] is not None:
vulns = e['vulns']
ip = e['ip_str']
for v in vulns:
cve = v
verified = vulns[v]['verified']
cvss = vulns[v]['cvss']
summary = vulns[v]['summary']
ref = vulns[v]['references']
references = ", ".join(ref)
'''
print("\nIP: {}".format(ip))
print("CVE: {}".format(v))
print("Verified: {}".format(verified))
print("CVSS: {}".format(cvss))
print("Summary: {}".format(summary))
print("References: {}".format(references))
'''
csv_out.append([ip,cve,verified,cvss,summary,references])
def write_csv():
fname = "cves-{}.csv".format(datetime.datetime.now().strftime("%Y%m%dT%H%M%S%f"))
with open(fname, 'w') as csvfile:
writer = csv.writer(csvfile, delimiter='\t')
writer.writerow(["IP\tCVE\tVerified\tCVSS\tSummary\tReferences"])
for line in csv_out:
line = "\t".join([str(e) for e in line])
writer.writerow([line])
print("Wrote {} results to {}".format(len(csv_out), fname))
def main():
if len(sys.argv) < 2:
print("Usage: {} <directory with shodan results files>".format(sys.argv[0]))
exit(1)
directory = sys.argv[1]
for root, dirs, files in os.walk(directory):
for name in files:
if re.findall("json|gz", name.split(".")[-1]):
p = os.path.join(root,name)
parse_shodan_file(p)
break
if len(csv_out) > 0:
write_csv()
else:
print("No CVEs in this directory")
if __name__ == "__main__":
main()
@jsdryan
Copy link

jsdryan commented Jul 12, 2020

When I was using steps above, it still showing "FileNotFoundError" 😞

@thesubtlety
Copy link
Author

Thanks for the note. I updated the script to fix the path issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment