|
@@ -16,18 +16,24 @@ class DebianModel:
|
|
"""
|
|
"""
|
|
module_path = os.path.dirname(__file__)
|
|
module_path = os.path.dirname(__file__)
|
|
|
|
|
|
|
|
+ """
|
|
|
|
+ TODO: Tables to manage.
|
|
|
|
+ """
|
|
|
|
+
|
|
|
|
+ dsatable = dict()
|
|
|
|
+ src2dsa = dict()
|
|
|
|
+ dsa2cve = dict()
|
|
|
|
+ cvetable = dict()
|
|
|
|
+ src2month = dict()
|
|
|
|
+ src2sloccount = dict()
|
|
|
|
+ src2pop = dict()
|
|
|
|
+ src2deps = dict()
|
|
|
|
+ pkg_with_cvss = dict()
|
|
|
|
+ src2sum = dict()
|
|
|
|
+
|
|
def __init__(self, action, configfile=os.path.join(module_path, 'config_default.txt')):
|
|
def __init__(self, action, configfile=os.path.join(module_path, 'config_default.txt')):
|
|
## DBs to track
|
|
## DBs to track
|
|
- self.dsatable = dict()
|
|
|
|
- self.src2dsa = dict()
|
|
|
|
- self.dsa2cve = dict()
|
|
|
|
- self.cvetable = dict()
|
|
|
|
- self.src2month = dict()
|
|
|
|
- self.src2sloccount = dict()
|
|
|
|
- self.src2pop = dict()
|
|
|
|
- self.src2deps = dict()
|
|
|
|
- self.pkg_with_cvss = dict()
|
|
|
|
- self.src2sum = dict()
|
|
|
|
|
|
+
|
|
|
|
|
|
## config
|
|
## config
|
|
self.configfile = configfile
|
|
self.configfile = configfile
|
|
@@ -36,21 +42,38 @@ class DebianModel:
|
|
raise IOError('Cannot open configuration file: ')
|
|
raise IOError('Cannot open configuration file: ')
|
|
(self.state, self.err) = self.load_state()
|
|
(self.state, self.err) = self.load_state()
|
|
|
|
|
|
- client = MongoClient()
|
|
|
|
|
|
+ self.client = MongoClient()
|
|
|
|
|
|
if action == 'update':
|
|
if action == 'update':
|
|
- (self.dsatable, self.src2dsa, self.dsa2cve, self.cvetable, self.src2month, self.src2sloccount, self.src2pop, self.src2deps) = self.load_dbs()
|
|
|
|
- self.update_dbs(self.dsatable, client, self.src2dsa, self.dsa2cve, self.src2month, self.cvetable, self.pkg_with_cvss)
|
|
|
|
- self.save_DBs(self.dsatable, self.src2dsa, self.dsa2cve, self.cvetable, self.src2month, self.src2sloccount, self.src2pop, self.src2deps, self.src2sum)
|
|
|
|
|
|
+ self.load_dbs()
|
|
|
|
+ self.update_dbs()
|
|
|
|
+ self.store_dbs()
|
|
self.save_state(self.state)
|
|
self.save_state(self.state)
|
|
# lstm.predict(src2month, src2sloccount, src2pop, src2deps)
|
|
# lstm.predict(src2month, src2sloccount, src2pop, src2deps)
|
|
|
|
+ """
|
|
|
|
+ with open('dsatable.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.dsatable.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('src2dsa.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.src2dsa.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('dsa2cve.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.dsa2cve.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('cvetable.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.cvetable.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('src2month.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.src2month.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('src2sloccount.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.src2sloccount.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('src2pop.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.src2pop.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ with open('src2deps.txt', 'w') as file:
|
|
|
|
+ file.write(str(sorted(self.src2deps.keys(), key=lambda x: str(x).lower())))
|
|
|
|
+ """
|
|
elif action == 'status':
|
|
elif action == 'status':
|
|
- (dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps) = self.load_dbs()
|
|
|
|
|
|
+ self.load_dbs()
|
|
# aptsec_status(sys.argv[2])
|
|
# aptsec_status(sys.argv[2])
|
|
elif action == 'show':
|
|
elif action == 'show':
|
|
- (dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps) = self.load_dbs()
|
|
|
|
- # src2sum = plot_all(src2month)
|
|
|
|
- # save_DBs(dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps, src2sum)
|
|
|
|
|
|
+ self.load_dbs()
|
|
|
|
+ self.store_dbs()
|
|
else:
|
|
else:
|
|
self.print_help(self)
|
|
self.print_help(self)
|
|
|
|
|
|
@@ -59,53 +82,60 @@ class DebianModel:
|
|
Loads the required databases into the model. Can either be implemented as read from file, or read from DB.
|
|
Loads the required databases into the model. Can either be implemented as read from file, or read from DB.
|
|
Currently reading it from files in the cache folder.
|
|
Currently reading it from files in the cache folder.
|
|
"""
|
|
"""
|
|
- cache_dir = os.path.join( self.module_path, self.config['DIR']['cache_dir'])
|
|
|
|
-
|
|
|
|
- tables = ['dsatable', 'src2dsa', 'dsa2cve', 'cvetable', 'src2deps', 'src2month', 'src2sloccount', 'src2pop']
|
|
|
|
- result = []
|
|
|
|
-
|
|
|
|
- for i in range(0, len(tables)):
|
|
|
|
- try:
|
|
|
|
- with open(os.path.join(cache_dir, tables[i])) as t:
|
|
|
|
- result.append(json.load(t))
|
|
|
|
- except (IOError, ValueError):
|
|
|
|
- print('Read cache ' + tables[i] + ' failed!! Maybe first run of the system?')
|
|
|
|
- result.append(dict())
|
|
|
|
-
|
|
|
|
- return tuple(result)
|
|
|
|
-
|
|
|
|
- def save_DBs(self, dsatable, src2dsa, dsa2cve, cvetable, src2month, src2sloccount, src2pop, src2deps, src2sum):
|
|
|
|
|
|
+ self.dsatable = self.load_single_db_from_cache('dsatable')
|
|
|
|
+ self.src2dsa = self.load_single_db_from_cache('src2dsa')
|
|
|
|
+ self.dsa2cve = self.load_single_db_from_cache('dsa2cve')
|
|
|
|
+ self.cvetable = self.load_single_db_from_cache('cvetable')
|
|
|
|
+ self.src2deps = self.load_single_db_from_cache('src2deps')
|
|
|
|
+ self.src2month = self.load_single_db_from_cache('src2month')
|
|
|
|
+ self.src2sloccount = self.load_single_db_from_cache('src2sloccount')
|
|
|
|
+ self.src2pop = self.load_single_db_from_cache('src2pop')
|
|
|
|
+
|
|
|
|
+ def load_single_db_from_cache(self, file_name):
|
|
cache_dir = os.path.join(self.module_path, self.config['DIR']['cache_dir'])
|
|
cache_dir = os.path.join(self.module_path, self.config['DIR']['cache_dir'])
|
|
-
|
|
|
|
- tables = ['dsatable', 'src2dsa', 'dsa2cve', 'cvetable', 'src2deps', 'src2sloccount', 'src2pop']
|
|
|
|
-
|
|
|
|
- for i in range(0, len(tables)):
|
|
|
|
- try:
|
|
|
|
- with open(os.path.join(cache_dir, tables[i]), 'w') as t:
|
|
|
|
- json.dump(dsatable, t, default=self.converter)
|
|
|
|
- except IOError:
|
|
|
|
- print('write cache dsatable failed!! Fatal error')
|
|
|
|
-
|
|
|
|
- cache_src2month = os.path.join(cache_dir, 'src2month')
|
|
|
|
|
|
+ try:
|
|
|
|
+ with open(os.path.join(cache_dir, file_name)) as f:
|
|
|
|
+ return json.load(f)
|
|
|
|
+ except (IOError, ValueError):
|
|
|
|
+ print('Read cache ' + file_name + ' failed!! Maybe first run of the system?')
|
|
|
|
+
|
|
|
|
+ def store_dbs(self):
|
|
|
|
+ self.store_db_single('dsatable', self.dsatable)
|
|
|
|
+ self.store_db_single('src2dsa', self.src2dsa)
|
|
|
|
+ self.store_db_single('dsa2cve', self.dsa2cve)
|
|
|
|
+ self.store_db_single('cvetable', self.cvetable)
|
|
|
|
+ self.store_db_single('src2deps', self.src2deps)
|
|
|
|
+ self.store_db_single('src2sloccount', self.src2sloccount)
|
|
|
|
+ self.store_db_single('src2pop', self.src2pop)
|
|
|
|
+
|
|
|
|
+ # src2month needs special handling
|
|
|
|
+ cache_src2month = os.path.join(self.module_path, self.config['DIR']['cache_dir'], 'src2month')
|
|
int_list = dict()
|
|
int_list = dict()
|
|
|
|
|
|
- for element in src2month:
|
|
|
|
- for i in range(len(src2month[element])):
|
|
|
|
|
|
+ for element in self.src2month:
|
|
|
|
+ for i in range(len(self.src2month[element])):
|
|
if element in int_list:
|
|
if element in int_list:
|
|
- int_list[element].append(int(src2month[element][i]))
|
|
|
|
|
|
+ int_list[element].append(int(self.src2month[element][i]))
|
|
else:
|
|
else:
|
|
int_list[element] = []
|
|
int_list[element] = []
|
|
- int_list[element].append(int(src2month[element][i]))
|
|
|
|
|
|
+ int_list[element].append(int(self.src2month[element][i]))
|
|
try:
|
|
try:
|
|
with open(cache_src2month, 'w') as fp:
|
|
with open(cache_src2month, 'w') as fp:
|
|
json.dump(int_list, fp, default=self.converter)
|
|
json.dump(int_list, fp, default=self.converter)
|
|
except IOError:
|
|
except IOError:
|
|
print('write cache src2month failed!! Fatal error')
|
|
print('write cache src2month failed!! Fatal error')
|
|
|
|
|
|
|
|
+ def store_db_single(self, file_name, db):
|
|
|
|
+ cache_dir = os.path.join(self.module_path, self.config['DIR']['cache_dir'])
|
|
|
|
+ try:
|
|
|
|
+ with open(os.path.join(cache_dir, file_name), 'w') as f:
|
|
|
|
+ json.dump(db, f, default=self.converter)
|
|
|
|
+ except (IOError, ValueError):
|
|
|
|
+ print('Read cache ' + file_name + ' failed!! Maybe first run of the system?')
|
|
|
|
+
|
|
def save_state(self, state):
|
|
def save_state(self, state):
|
|
"""Save state, different from DBs in that we always need it"""
|
|
"""Save state, different from DBs in that we always need it"""
|
|
state_file = os.path.join(self.module_path, self.config['DIR']['cache_dir'], 'state')
|
|
state_file = os.path.join(self.module_path, self.config['DIR']['cache_dir'], 'state')
|
|
-
|
|
|
|
try:
|
|
try:
|
|
with open(state_file, 'w') as sf:
|
|
with open(state_file, 'w') as sf:
|
|
json.dump(state, sf)
|
|
json.dump(state, sf)
|
|
@@ -119,56 +149,51 @@ class DebianModel:
|
|
if isinstance(o, np.float):
|
|
if isinstance(o, np.float):
|
|
return o.astype(int)
|
|
return o.astype(int)
|
|
|
|
|
|
- def update_dbs(self, dsatable, client, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss):
|
|
|
|
|
|
+ def update_dbs(self):
|
|
now = datetime.datetime.now()
|
|
now = datetime.datetime.now()
|
|
new_adv = DebianAdvisory.checkDSAs(self.state, self.config)
|
|
new_adv = DebianAdvisory.checkDSAs(self.state, self.config)
|
|
|
|
|
|
for id in new_adv:
|
|
for id in new_adv:
|
|
- if id in dsatable:
|
|
|
|
|
|
+ if id in self.dsatable:
|
|
logging.info(self.state['vendor'] + ' advisory ' + id + ' already known.\n')
|
|
logging.info(self.state['vendor'] + ' advisory ' + id + ' already known.\n')
|
|
else:
|
|
else:
|
|
## store advisory and parse it
|
|
## store advisory and parse it
|
|
- dsatable[id] = new_adv[id]
|
|
|
|
- self.updateCVETables(id, dsatable, self.state, src2dsa, dsa2cve, cvetable, client)
|
|
|
|
|
|
+ self.dsatable[id] = new_adv[id]
|
|
|
|
+ self.updateCVETables(id)
|
|
|
|
|
|
# recompute all pkg statistics
|
|
# recompute all pkg statistics
|
|
- for srcpkg in src2dsa:
|
|
|
|
- self.processCVEs(srcpkg, now, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss, self.config)
|
|
|
|
-
|
|
|
|
- return 0
|
|
|
|
|
|
+ for srcpkg in self.src2dsa:
|
|
|
|
+ self.processCVEs(srcpkg, now)
|
|
|
|
|
|
- def updateCVETables(self, myid, dsatable, state, src2dsa, dsa2cve, cvetable, client):
|
|
|
|
|
|
+ def updateCVETables(self, myid):
|
|
|
|
|
|
- logging.info('Updating vulnerability database with advisory ' + state['vendor'] + str(myid) + ' \n')
|
|
|
|
|
|
+ logging.info('Updating vulnerability database with advisory ' + self.state['vendor'] + str(myid) + ' \n')
|
|
|
|
|
|
- adv = dsatable[myid]
|
|
|
|
|
|
+ adv = self.dsatable[myid]
|
|
dsastats = DebianAdvisory.parseDSAhtml(adv)
|
|
dsastats = DebianAdvisory.parseDSAhtml(adv)
|
|
|
|
|
|
dsastats = DebianAdvisory.fixDSAquirks(myid, dsastats)
|
|
dsastats = DebianAdvisory.fixDSAquirks(myid, dsastats)
|
|
|
|
|
|
for srcpkg in dsastats[0]:
|
|
for srcpkg in dsastats[0]:
|
|
- if srcpkg in src2dsa:
|
|
|
|
- src2dsa[srcpkg].append(myid)
|
|
|
|
|
|
+ if srcpkg in self.src2dsa:
|
|
|
|
+ self.src2dsa[srcpkg].append(myid)
|
|
else:
|
|
else:
|
|
- src2dsa[srcpkg] = []
|
|
|
|
- src2dsa[srcpkg].append(myid)
|
|
|
|
|
|
+ self.src2dsa[srcpkg] = []
|
|
|
|
+ self.src2dsa[srcpkg].append(myid)
|
|
|
|
|
|
- dsa2cve[str(myid)] = dsastats[2]
|
|
|
|
|
|
+ self.dsa2cve[str(myid)] = dsastats[2]
|
|
|
|
|
|
|
|
|
|
for cve_id in dsastats[2]:
|
|
for cve_id in dsastats[2]:
|
|
# No fetch CVE We use mongodb and cve-search
|
|
# No fetch CVE We use mongodb and cve-search
|
|
- cve = CVEParse.fetchCVE(cve_id, client)
|
|
|
|
|
|
+ cve = CVEParse.fetchCVE(cve_id, self.client)
|
|
cvestats = CVEParse.parseCVE(cve_id, cve)
|
|
cvestats = CVEParse.parseCVE(cve_id, cve)
|
|
finaldate = cvestats[0]
|
|
finaldate = cvestats[0]
|
|
|
|
|
|
if cvestats[0] > dsastats[1] or cvestats[0] == 0:
|
|
if cvestats[0] > dsastats[1] or cvestats[0] == 0:
|
|
finaldate = dsastats[1]
|
|
finaldate = dsastats[1]
|
|
|
|
|
|
- cvedata = (finaldate, dsastats[1] - finaldate, cvestats[1], cvestats[2], cvestats[3])
|
|
|
|
- cvetable[cve_id] = cvedata
|
|
|
|
-
|
|
|
|
- return cvetable
|
|
|
|
|
|
+ self.cvetable[cve_id] = (finaldate, dsastats[1] - finaldate, cvestats[1], cvestats[2], cvestats[3])
|
|
|
|
|
|
@staticmethod
|
|
@staticmethod
|
|
def print_help():
|
|
def print_help():
|
|
@@ -204,34 +229,32 @@ class DebianModel:
|
|
|
|
|
|
return state, err
|
|
return state, err
|
|
|
|
|
|
-
|
|
|
|
- def processCVEs(self, pkg, now, src2dsa, dsa2cve, src2month, cvetable, pkg_with_cvss, config):
|
|
|
|
|
|
+ def processCVEs(self, srcpkg, now):
|
|
"""
|
|
"""
|
|
compute and store MTBF, MTBR and Scores of each src pkg
|
|
compute and store MTBF, MTBR and Scores of each src pkg
|
|
output: %src2mtbf
|
|
output: %src2mtbf
|
|
(srcpkg=> ())
|
|
(srcpkg=> ())
|
|
"""
|
|
"""
|
|
|
|
+
|
|
stats = [now, 0, 0, 0, 0, 0, 0]
|
|
stats = [now, 0, 0, 0, 0, 0, 0]
|
|
- mylambda = config['TRUST']['lambda']
|
|
|
|
cvestats = dict()
|
|
cvestats = dict()
|
|
- logging.info('Processing package: ' + pkg + '.\n')
|
|
|
|
|
|
+ logging.info('Processing package: ' + srcpkg + '.\n')
|
|
|
|
|
|
## keep track of the number of low-medium-high severity vulnerabilities
|
|
## keep track of the number of low-medium-high severity vulnerabilities
|
|
## TODO see how cvss affects vulnerability prediction - if some packages show patterns
|
|
## TODO see how cvss affects vulnerability prediction - if some packages show patterns
|
|
- temp_cvss = 0.0
|
|
|
|
with_cvss = dict()
|
|
with_cvss = dict()
|
|
|
|
|
|
## To eliminate duplicate cves
|
|
## To eliminate duplicate cves
|
|
haveseen = dict()
|
|
haveseen = dict()
|
|
|
|
|
|
## cvestats = (date: number)
|
|
## cvestats = (date: number)
|
|
- for dsa_id in src2dsa[pkg]:
|
|
|
|
- for cve_id in dsa2cve[str(dsa_id)]:
|
|
|
|
|
|
+ for dsa_id in self.src2dsa[srcpkg]:
|
|
|
|
+ for cve_id in self.dsa2cve[str(dsa_id)]:
|
|
if cve_id in haveseen:
|
|
if cve_id in haveseen:
|
|
continue
|
|
continue
|
|
else:
|
|
else:
|
|
haveseen[cve_id] = 1
|
|
haveseen[cve_id] = 1
|
|
- tt = cvetable[cve_id][0]
|
|
|
|
|
|
+ tt = self.cvetable[cve_id][0]
|
|
if tt in cvestats:
|
|
if tt in cvestats:
|
|
cvestats[tt] += 1
|
|
cvestats[tt] += 1
|
|
else:
|
|
else:
|
|
@@ -241,11 +264,11 @@ class DebianModel:
|
|
## Date at the moment taken from CVE? - not sure.
|
|
## Date at the moment taken from CVE? - not sure.
|
|
|
|
|
|
## with_cvss = (date: number low, number med, number high)
|
|
## with_cvss = (date: number low, number med, number high)
|
|
- for dsa_id in src2dsa[pkg]:
|
|
|
|
- for cve_id in dsa2cve[str(dsa_id)]:
|
|
|
|
- tt = cvetable[cve_id][0]
|
|
|
|
|
|
+ for dsa_id in self.src2dsa[srcpkg]:
|
|
|
|
+ for cve_id in self.dsa2cve[str(dsa_id)]:
|
|
|
|
+ tt = self.cvetable[cve_id][0]
|
|
try:
|
|
try:
|
|
- temp_cvss = float(cvetable[cve_id][2])
|
|
|
|
|
|
+ temp_cvss = float(self.cvetable[cve_id][2])
|
|
except TypeError:
|
|
except TypeError:
|
|
print(cve_id)
|
|
print(cve_id)
|
|
continue
|
|
continue
|
|
@@ -270,27 +293,20 @@ class DebianModel:
|
|
if stats[1] < 1:
|
|
if stats[1] < 1:
|
|
return
|
|
return
|
|
|
|
|
|
- prev_date = 0
|
|
|
|
- weight = 0
|
|
|
|
-
|
|
|
|
dates = sorted(cvestats, key=cvestats.get)
|
|
dates = sorted(cvestats, key=cvestats.get)
|
|
try:
|
|
try:
|
|
stats[0] = dates[0]
|
|
stats[0] = dates[0]
|
|
except IndexError:
|
|
except IndexError:
|
|
- print(pkg + str(dates))
|
|
|
|
|
|
+ print(srcpkg + str(dates))
|
|
stats[0] = 0
|
|
stats[0] = 0
|
|
|
|
|
|
count = sum(cvestats.values())
|
|
count = sum(cvestats.values())
|
|
|
|
|
|
- print(pkg + ' ' + str(count))
|
|
|
|
-
|
|
|
|
- # pkg_with_cvss[pkg] = with_cvss
|
|
|
|
- self.format_data(pkg, with_cvss, pkg_with_cvss, True)
|
|
|
|
|
|
+ self.format_data(srcpkg, with_cvss, self.pkg_with_cvss, True)
|
|
|
|
|
|
- self.format_data(pkg, cvestats, src2month, False)
|
|
|
|
|
|
+ self.format_data(srcpkg, cvestats, self.src2month, False)
|
|
|
|
|
|
def format_data(self, pkg, cvestats, src2month, cvss):
|
|
def format_data(self, pkg, cvestats, src2month, cvss):
|
|
-
|
|
|
|
x = []
|
|
x = []
|
|
y = []
|
|
y = []
|
|
monthyear = []
|
|
monthyear = []
|