Mercurial > farol > farolluz
view farolluz/vulnerability.py @ 38:7ee2dec783c1
CHANGES: Mention the new HTML export format.
author | Benoît Allard <benoit.allard@greenbone.net> |
---|---|
date | Wed, 17 Dec 2014 11:24:55 +0100 |
parents | e317097af486 |
children | 2e36289616db |
line wrap: on
line source
# -*- coding: utf-8 -*- # # Authors: # BenoƮt Allard <benoit.allard@greenbone.net> # # Copyright: # Copyright (C) 2014 Greenbone Networks GmbH # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. """\ Vulnerability Objects related to CVRF Documents """ from .common import ValidationError from .document import CVRFPublisher class CVRFVulnerabilityID(object): def __init__(self, systemname, value): self._systemname = systemname self._value = value def validate(self): if not self._systemname: raise ValidationError('A Vulnerability ID must have a System Name') if not self._value: raise ValidationError('A Vulnerability ID must have a value') class CVRFVulnerability(object): def __init__(self, ordinal): self._ordinal = ordinal self._title = None self._id = None self._notes = [] self._discoverydate = None self._releasedate = None self._involvements = [] self._cve = None self._cwes = [] self._productstatuses = [] self._threats = [] self._cvsss = [] self._remediations = [] self._references = [] self._acknowledgments = [] def setTitle(self, title): self._title = title def setID(self, _id): self._id = _id def addNote(self, note): self._notes.append(note) def setDiscoveryDate(self, date): self._discoverydate = date def setReleaseDate(self, date): self._releasedate = date def addInvolvement(self, involvement): self._involvements.append(involvement) def setCVE(self, cve): self._cve = cve def addCWE(self, cwe): self._cwes.append(cwe) def addProductStatus(self, productstatus): self._productstatuses.append(productstatus) def addThreat(self, threat): self._threats.append(threat) def addCVSSSet(self, cvss_set): self._cvsss.append(cvss_set) def addRemediation(self, remediation): self._remediations.append(remediation) def addReference(self, ref): self._references.append(ref) def addAcknowledgment(self, ack): self._acknowledgments.append(ack) def getTitle(self): """ return something that can be used as a title """ if self._title: if self._id: return "%s (%s)" % (self._title, self._id._value) return self._title if self._id: return self._id._value return "#%d" % self._ordinal def getNote(self, ordinal): for note in self._notes: if note._ordinal == ordinal: return note return None def mentionsProdId(self, productid): """ Returns in which sub element, self is mentioning the productid """ for category in (self._productstatuses, self._threats, self._cvsss, self._remediations): for subelem in category: if productid in subelem._productids: yield subelem def isMentioningProdId(self, productid): """ Returns if self is mentioning the productid """ for e in self.mentionsProdId(productid): # We only need to know if the generator yield at least one elem. return True return False def mentionsGroupId(self, groupid): for category in (self._threats, self._remediations): for subelem in category: if groupid in subelem._groupids: yield subelem def isMentioningGroupId(self, groupid): for _ in self.mentionsGroupId(groupid): # We only need to know if the generator yield at least one elem. return True return False def validate(self, productids, groupids): if not self._ordinal: raise ValidationError('A Vulnerability must have an ordinal') if self._id is not None: self._id.validate() ordinals = set() for note in self._notes: note.validate() if note._ordinal in ordinals: raise ValidationError('Vulnerability Note Ordinal %d duplicated' % note._ordinal) ordinals.add(note._ordinal) for involvement in self._involvements: involvement.validate() for cwe in self._cwes: cwe.validate() for status in self._productstatuses: status.validate(productids) pids = set() for status in self._productstatuses: for pid in status._productids: if pid in pids: raise ValidationError('ProductID %s mentionned in two different ProductStatuses for Vulnerability %d' % (pid, self._ordinal)) pids.add(pid) for threat in self._threats: threat.validate(productids, groupids) for cvss in self._cvsss: cvss.validate(productids) pids = set() for cvss in self._cvsss: for pid in (cvss._productids or productids): if pid in pids: raise ValidationError('ProductID %s mentionned in two different CVSS Score Sets for Vulnerability %d' % (pid, self._ordinal)) pids.add(pid) for remediation in self._remediations: remediation.validate(productids, groupids) for reference in self._references: reference.validate() for acknowledgment in self._acknowledgments: acknowledgment.validate() class CVRFInvolvement(object): PARTIES = CVRFPublisher.TYPES STATUSES = ('Open', 'Disputed', 'In Progress', 'Completed', 'Contact Attempted', 'Not Contacted') def __init__(self, party, status): self._party = party self._status = status self._description = None def setDescription(self, description): self._description = description def getTitle(self): return "From %s: %s" % (self._party, self._status) def validate(self): if not self._party: raise ValidationError('An Involvement must have a Party') if self._party not in self.PARTIES: raise ValidationError("An Involvement's Party must be one of %s" % ', '.join(self.PARTIES)) if not self._status: raise ValidationError('An Involvement must have a Status') if self._status not in self.STATUSES: raise ValidationError("An Involvement's Status must be one of %s" % ', '.join(self.STATUSES)) class CVRFCWE(object): def __init__(self, _id, value): self._id = _id self._value = value def validate(self): if not self._id: raise ValidationError('A CWE must have an ID') if not self._value: raise ValidationError('A CWE must have a description') class CVRFProductStatus(object): TYPES = ('First Affected', 'Known Affected', 'Known Not Affected', 'First Fixed', 'Fixed', 'Recommended', 'Last Affected') NAME = "Product Status" def __init__(self, _type): self._type = _type self._productids = [] def addProductID(self, productid): self._productids.append(productid) def getTitle(self): return "%s: %d products" % (self._type, len(self._productids)) def validate(self, productids): if not self._type: raise ValidationError('A Product Status must have a Type') if self._type not in self.TYPES: raise ValidationError("A Product Status' Type must be one of %s" % ', '.join(self.TYPES)) if len(self._productids) < 1: raise ValidationError('A Product Status must mention at least one Product') for productid in self._productids: if productid not in productids: raise ValidationError('Unknown ProductID: %s' % productid) class CVRFThreat(object): TYPES = ('Impact', 'Exploit Status', 'Target Set') NAME = "Threat" def __init__(self, _type, description): self._type = _type self._description = description self._date = None self._productids = [] self._groupids = [] def setDate(self, date): self._date = date def addProductID(self, productid): self._productids.append(productid) def addGroupID(self, groupid): self._groupids.append(groupid) def getTitle(self): return self._type def validate(self, productids, groupids): if not self._type: raise ValidationError('A Threat must have a Type') if self._type not in self.TYPES: raise ValidationError("A Threat's Type must be one of %s" % ', '.join(self.TYPES)) if not self._description: raise ValidationError('A Threat must have a Description') for productid in self._productids: if productid not in productids: raise ValidationError('Unknown ProductID: %s' % productid) for groupid in self._groupids: if groupid not in groupids: raise ValidationError('Unknown GroupID: %s' % groupid) class CVRFCVSSSet(object): # To determine the base Score VALUES = {'AV': {'L':0.395, 'A':0.646, 'N':1.0}, 'AC': {'H':0.35, 'M':0.61 ,'L':0.71}, 'Au': {'M':0.45, 'S':0.56, 'N':0.704}, 'C': {'N':0.0, 'P':0.275, 'C':0.66}, 'I': {'N':0.0, 'P':0.275, 'C':0.66}, 'A': {'N':0.0, 'P':0.275, 'C':0.66}} NAME = "CVSS Score Set" def __init__(self, basescore): self._basescore = basescore self._temporalscore = None self._environmentalscore = None self._vector = None self.vector = None self._productids = [] def setTemporalScore(self, tempscore): self._temporalscore = tempscore def setEnvironmentalScore(self, envscore): self._environmentalscore = envscore def setVector(self, vector): self._vector = vector if vector is None: self.vector = vector return try: self.vector = {} for component in vector[:26].split('/'): name, value = component.split(':') self.vector[name] = self.VALUES[name][value] except (KeyError, ValueError): self.vector = None def addProductID(self, productid): self._productids.append(productid) def baseScore(self): v = self.vector # make an alias for shorter lines exploitability = 20 * v['AV'] * v['AC'] * v['Au'] impact = 10.41 * (1 - (1 - v['C']) * (1 - v['I']) * (1 - v['A'])) def f(i): return 0 if i == 0 else 1.176 return ((0.6 * impact) + (0.4 * exploitability) - 1.5) * f(impact) def validate(self, productids): if not self._basescore: raise ValidationError('A CVSS Score Set must have a Base Score') if self._vector and not self.vector: raise ValidationError('Syntax Error in CVSS Vector') if self.vector and (abs(self._basescore - self.baseScore()) >= 0.05): raise ValidationError('Inconsistency in CVSS Score Set between Vector (%f) and Base Score (%f)' % (self.baseScore(), self._basescore)) for productid in self._productids: if productid not in productids: raise ValidationError('Unknown ProductID: %s' % productid) class CVRFRemediation(object): TYPES = ('Workaround', 'Mitigation', 'Vendor Fix', 'None Available', 'Will Not Fix') NAME = "Remediation" def __init__(self, _type, description): self._type = _type self._description = description self._date = None self._entitlement = None self._url = None self._productids = [] self._groupids = [] def setDate(self, date): self._date = date def setEntitlement(self, entitlement): self._entitlement = entitlement def setURL(self, url): self._url = url def addProductID(self, productid): self._productids.append(productid) def addGroupID(self, groupid): self._groupids.append(groupid) def getTitle(self): return self._type def validate(self, productids, groupids): if not self._type: raise ValidationError('A Remediation must have a Type') if self._type not in self.TYPES: raise ValidationError("A Remediation's Type must be one of %s" % ', '.join(self.TYPES)) if not self._description: raise ValidationError('A Remediation must have a Description') for productid in self._productids: if productid not in productids: raise ValidationError('Unknown ProductID: %s' % productid) for groupid in self._groupids: if groupid not in groupids: raise ValidationError('Unknown GroupID: %s' % groupid)