aboutsummaryrefslogtreecommitdiffstats
path: root/bin/nist/srtool_nist.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/nist/srtool_nist.py')
-rwxr-xr-xbin/nist/srtool_nist.py105
1 files changed, 93 insertions, 12 deletions
diff --git a/bin/nist/srtool_nist.py b/bin/nist/srtool_nist.py
index c7a61dce..e93f0882 100755
--- a/bin/nist/srtool_nist.py
+++ b/bin/nist/srtool_nist.py
@@ -219,8 +219,8 @@ def CVE_ItemToSummary(CVE_Item,header_only=False):
summary['packages'] = ''
# Fix score to sortable string value
- summary['cvssV3_baseScore'] = '%02.2f' % float(summary['cvssV3_baseScore']) if summary['cvssV3_baseScore'] else ''
- summary['cvssV2_baseScore'] = '%02.2f' % float(summary['cvssV2_baseScore']) if summary['cvssV2_baseScore'] else ''
+ summary['cvssV3_baseScore'] = '%02.1f' % float(summary['cvssV3_baseScore']) if summary['cvssV3_baseScore'] else ''
+ summary['cvssV2_baseScore'] = '%02.1f' % float(summary['cvssV2_baseScore']) if summary['cvssV2_baseScore'] else ''
# The CVE table only needs the header, CVE details needs the rest
if header_only:
@@ -759,14 +759,14 @@ def file_date(filename,utc=False):
# fetch_cve: extract and return the meta data for a specific CVE
#
-def fetch_cve(cve_name,cve_source_file):
+def do_fetch_cve(cve_name,cve_source_file,use_cache=True):
# Fetch cached data, else extract data from datasource file
cache_path = os.path.join(srtool_basepath, nist_cache_dir)
cve_cache_path = os.path.join(cache_path, cve_name + ".json")
#check if in cache, and use if exists. Else fetch from appropriate CVE JSON feed file
CVE_Item = None
- if (os.path.isfile(cve_cache_path)):
+ if use_cache and os.path.isfile(cve_cache_path):
try:
f = open(cve_cache_path, 'r')
CVE_Item = json.load(f)
@@ -792,26 +792,102 @@ def fetch_cve(cve_name,cve_source_file):
os.makedirs(cache_path)
except:
pass
- cve_cache_file = open(cve_cache_path, "w+") #write the cve to json file in cache
- cve_cache_file.write(json.dumps(CVE_Item))
+ if use_cache:
+ cve_cache_file = open(cve_cache_path, "w+") #write the cve to json file in cache
+ cve_cache_file.write(json.dumps(CVE_Item))
break
except Exception as e:
print("Description=ERROR creating CVE cache file '%s':%s" % (cve_source_file,e))
return
else:
# No data source for details
- return
+ return None
if not CVE_Item:
print("description=There is no CVE record for %s in the loaded NIST public CVE database." % cve_name)
- return
+ return None
# Translate a CVE_Item JSON node
- summary = CVE_ItemToSummary(CVE_Item)
+ return(CVE_ItemToSummary(CVE_Item))
+
+def fetch_cve(cve_name,cve_source_file):
+ summary = do_fetch_cve(cve_name,cve_source_file)
+ if not summary:
+ print("description=There is no CVE record for %s in the loaded NIST public CVE database." % cve_name)
+ else:
+ # Return the results
+ for key in summary.keys():
+ print('%s=%s' % (key,summary[key]))
+
+def cve_summary(cve_name):
+
+ DSMAP_FILE = 0
+ DSMAP_DESC = 1
+ DSMAP_MOD = 2
+ DSMAP_UPDATE = 3
+
+ conn = sqlite3.connect(srtDbName)
+ cur_ds = conn.cursor()
+ cur_cve = conn.cursor()
+ base_id = []
+ modified_id = []
+
+ def get_file(lookup):
+ for param in lookup.split(' '):
+ if param.startswith('--file='):
+ return(param.replace('--file=',''))
+ return('')
+
+ def show_summary(cve_name,datasource_map):
+ summary = do_fetch_cve(cve_name,datasource_map[DSMAP_FILE],False)
+ if summary:
+ desc_sum = 0
+ description = summary['description']
+ for ch in description:
+ desc_sum += ord(ch)
+ if 37 < len(description):
+ description = "%-37s..." % description[:37]
+ print(" * Name:%s in %s (%s,%s)" % (summary['name'],datasource_map[DSMAP_FILE],datasource_map[DSMAP_MOD],datasource_map[DSMAP_UPDATE]))
+ print(" description :%-40s [sum=%d]" % (description,desc_sum))
+ print(" cvssV3_baseScore :%s" % summary['cvssV3_baseScore'])
+ print(" cvssV3_baseSeverity:%s" % summary['cvssV3_baseSeverity'])
+ print(" cvssV2_baseScore :%s" % summary['cvssV2_baseScore'])
+ print(" cvssV2_severity :%s" % summary['cvssV2_severity'])
+ print(" lastModifiedDate :%s" % summary['lastModifiedDate'])
+ else:
+ print(" There is no CVE record for %s in %s" % (cve_name,base_file))
+
+ cur_ds.execute('SELECT * FROM orm_datasource;')
+ datasource_map = {}
+ for datasource in cur_ds:
+ #print("Datasource[%d]='%s'" % (datasource[ORM.DATASOURCE_ID],datasource[ORM.DATASOURCE_DESCRIPTION]))
+
+ # DataSource Map is [cve_file,ds_desc,ds_lastmodifieddate,ds_lastupdateddate]
+ datasource_map[datasource[ORM.DATASOURCE_ID]] = ['',datasource[ORM.DATASOURCE_DESCRIPTION],datasource[ORM.DATASOURCE_LASTMODIFIEDDATE],datasource[ORM.DATASOURCE_LASTUPDATEDDATE]]
+ if ('nist' == datasource[ORM.DATASOURCE_SOURCE]) and ('NIST Modified Data' == datasource[ORM.DATASOURCE_DESCRIPTION]):
+ datasource_map[datasource[ORM.DATASOURCE_ID]][DSMAP_FILE] = get_file(datasource[ORM.DATASOURCE_LOOKUP])
+ modified_id = datasource[ORM.DATASOURCE_ID]
+ elif ('nist' == datasource[ORM.DATASOURCE_SOURCE]) and datasource[ORM.DATASOURCE_CVE_FILTER] and cve_name.startswith(datasource[ORM.DATASOURCE_CVE_FILTER]):
+ datasource_map[datasource[ORM.DATASOURCE_ID]][DSMAP_FILE] = get_file(datasource[ORM.DATASOURCE_LOOKUP])
+ base_id = datasource[ORM.DATASOURCE_ID]
+ #print("FOO2:%s,%s" % (base_id,modified_id))
+
+ # Return the NIST results
+ print("NIST Summary:")
+ show_summary(cve_name,datasource_map[base_id])
+ show_summary(cve_name,datasource_map[modified_id])
+ # Return the DataSource mapping results
+ print("DataSource Summary:")
+ cur_cve.execute('SELECT * FROM orm_cve WHERE name = "%s"' % cve_name)
+ for i,cve in enumerate(cur_cve):
+ cur_ds.execute('SELECT * FROM orm_cvesource WHERE cve_id = %d' % cve[ORM.CVE_ID])
+ for j,cs in enumerate(cur_ds):
+ datasource_id = cs[ORM.CVESOURCE_DATASOURCE_ID]
+ if datasource_id in datasource_map:
+ print(" [%2d] %s" % (j+1,datasource_map[cs[ORM.CVESOURCE_DATASOURCE_ID]][DSMAP_DESC]))
+ else:
+ print(" [%2d] Unknown DataSource ID %d" % (j+1,cs[ORM.CVESOURCE_DATASOURCE_ID]))
- # Return the results
- for key in summary.keys():
- print('%s=%s' % (key,summary[key]))
#######################################################################
# update_cve_list: Update CVE records for a list of CVEs
@@ -960,7 +1036,9 @@ def main(argv):
parser.add_argument('--download-only', action='store_const', const='download_nist', dest='command', help='Download the NIST source CVE file(s), load CVEs on demand only')
parser.add_argument('--update-cve-list', '-l', dest='update_cve_list', help='Update list of CVEs to database')
parser.add_argument('--update-existing-cves', '-L', dest='update_existing_cves', help='Update list of existing CVEs to database')
+
parser.add_argument('--cve-detail', '-d', dest='cve_detail', help='Lookup CVE data')
+ parser.add_argument('--cve-summary', '-S', dest='cve_summary', help='Quick summary of CVE data')
parser.add_argument('--source', dest='source', help='Local CVE source file')
parser.add_argument('--url-file', dest='url_file', help='CVE URL extension')
@@ -995,6 +1073,9 @@ def main(argv):
elif args.update_existing_cves:
update_existing_cves(ACTION_UPDATE_CVE,args.update_existing_cves)
return
+ elif args.cve_summary:
+ cve_summary(args.cve_summary)
+ return
# Required parameters to continue
if not args.cve_file: