diff options
Diffstat (limited to 'bin/nist/srtool_nist.py')
-rwxr-xr-x | bin/nist/srtool_nist.py | 105 |
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: |