aboutsummaryrefslogtreecommitdiffstats
path: root/bin/mitre/srtool_mitre.py
diff options
context:
space:
mode:
Diffstat (limited to 'bin/mitre/srtool_mitre.py')
-rwxr-xr-xbin/mitre/srtool_mitre.py52
1 files changed, 45 insertions, 7 deletions
diff --git a/bin/mitre/srtool_mitre.py b/bin/mitre/srtool_mitre.py
index 28bd52ae..0464156a 100755
--- a/bin/mitre/srtool_mitre.py
+++ b/bin/mitre/srtool_mitre.py
@@ -32,8 +32,9 @@ import re
import xml.etree.ElementTree as ET
import argparse
import shutil
-from datetime import datetime, date
import sqlite3
+from datetime import datetime, date, timedelta
+import pytz
from urllib.request import urlopen, URLError, Request
from urllib.parse import urlparse
@@ -89,6 +90,39 @@ def srt_error_log(msg):
f1.write("|" + msg + "|\n" )
f1.close()
+
+# Newly discovered or updated CVEs default to NEW for triage
+# Inited CVEs default to HISTORICAL, unless they are within the courtesy CVE_INIT_NEW_DELTA
+init_new_date = None
+def get_cve_default_status(is_init,publishedDate):
+ global init_new_date
+
+ if None == init_new_date:
+ # Precalculate and cache the relative 'new' date for efficiency
+ conn = sqlite3.connect(srtDbName)
+ cur = conn.cursor()
+ sql = '''SELECT * FROM orm_srtsetting WHERE name=?'''
+ CVE_INIT_NEW_DELTA = cur.execute(sql, ('CVE_INIT_NEW_DELTA',)).fetchone()
+ if CVE_INIT_NEW_DELTA is None:
+ cve_init_new_delta = 30
+ else:
+ cve_init_new_delta = int(CVE_INIT_NEW_DELTA[ORM.SRTSETTING_VALUE])
+
+ date_delta = timedelta(days=cve_init_new_delta)
+ init_new_date = datetime.now(pytz.utc) - date_delta
+ #print("\nPreset new data = %s" % init_new_date.strftime("%Y%m%d"))
+ init_new_date = init_new_date.strftime("%Y-%m-%d")
+
+ if is_init:
+ # Note: the NIST 'published date' is in the format "2017-05-11", so do a simple string compare
+ #print("INIT status: %s versus %s" % (init_new_date,publishedDate))
+ if not publishedDate or (publishedDate > init_new_date):
+ return ORM.STATUS_NEW
+ else:
+ return ORM.STATUS_HISTORICAL
+ else:
+ return ORM.STATUS_NEW
+
#################################
# Fetch a CVRF record from Mitre
# REST API, cache the results
@@ -176,7 +210,6 @@ def fetch_cve(cve_name,cvrf_xml_file):
with open(cache_file, 'r') as fp:
for line in fp:
line = line.strip()
- #print("FOO:'%s'" % line)
if line.startswith('Description'): results['description'] = '%s[EOL]%s' % (line.replace('Description=','').replace('\\n','').replace('\\r',' '),results['description'])
elif line.startswith('Published'): results['publishedDate'] = line.replace('Published=','')
elif line.startswith('Modified'): results['lastModifiedDate'] = line.replace('Modified=','')
@@ -226,8 +259,10 @@ def init_mitre_file(source,url_file,datasource_file,force_update):
#################################
# append_cve_database
#
+# Create new CVE record if not already added by NIST scan
+# so that non-public CVEs can be tracked
-def append_cve_database(file_xml):
+def append_cve_database(is_init,file_xml):
tree = ET.parse(file_xml)
root = tree.getroot()
@@ -275,9 +310,12 @@ def append_cve_database(file_xml):
cve_id = cve[ORM.CVE_ID]
print("MITRE:FOUND %20s\r" % cve_name, end='')
else:
+ # Get the default CVE status
+ status = get_cve_default_status(is_init,summary['Published'])
+
sql = ''' INSERT into orm_cve (name, name_sort, priority, status, comments, comments_private, cve_data_type, cve_data_format, cve_data_version, public, publish_state, publish_date, description, publishedDate, lastModifiedDate, recommend, recommend_list, cvssV3_baseScore, cvssV3_baseSeverity, cvssV2_baseScore, cvssV2_severity, srt_updated, packages)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'''
- cur.execute(sql, (cve_name, get_name_sort(cve_name), ORM.PRIORITY_UNDEFINED, ORM.STATUS_HISTORICAL, '', '', '', '', '', 1, ORM.PUBLISH_UNPUBLISHED, '', summary['Description'], summary['Published'], summary['Modified'],'', '', '', '', '', '', datetime.now(),''))
+ cur.execute(sql, (cve_name, get_name_sort(cve_name), ORM.PRIORITY_UNDEFINED, status, '', '', '', '', '', 1, ORM.PUBLISH_UNPUBLISHED, '', summary['Description'], summary['Published'], summary['Modified'],'', '', '', '', '', '', datetime.now(),''))
cve_id = cur.lastrowid
print("MITRE:ADDED %20s" % cve_name)
@@ -363,7 +401,7 @@ def main(argv):
# setup
parser = argparse.ArgumentParser(description='srtool_mitre.py: manage Mitre CVE data')
- parser.add_argument('--initialize', '-i', action='store_const', const='init_mitre', dest='command', help='Download the Mitre source CVE file')
+ parser.add_argument('--initialize', '-I', action='store_const', const='init_mitre', dest='command', help='Download the Mitre source CVE file')
parser.add_argument('--update', '-u', action='store_const', const='update_mitre', dest='command', help='Update the Mitre source CVE file')
parser.add_argument('--source', dest='source', help='Local CVE source file')
parser.add_argument('--url-file', dest='url_file', help='CVE URL extension')
@@ -409,10 +447,10 @@ def main(argv):
if 'init_mitre' == args.command:
init_mitre_file(args.source,args.url_file,args.cve_file,args.force_update)
- append_cve_database(args.cve_file)
+ append_cve_database(True,args.cve_file)
elif 'update_mitre' == args.command:
- # No difference from init at this time
init_mitre_file(args.source,args.url_file,args.cve_file,args.force_update)
+ append_cve_database(False,args.cve_file)
else:
print("Command not found")