Mercurial > farol > farolluz
view farolluz/parsers/cve.py @ 48:3826f2701ff2
CPE: Add the possibility to add ourself integrally to the product tree
author | Benoît Allard <benoit.allard@greenbone.net> |
---|---|
date | Tue, 30 Dec 2014 12:30:19 +0100 |
parents | 075519975933 |
children |
line wrap: on
line source
# -*- coding: utf-8 -*- # Description: # Methods for parsing CVE XML documents # # 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. """\ Methods for parsing of CVE XML Documents Ref: http://scap.nist.gov/schema/vulnerability/0.4 """ from __future__ import absolute_import import xml.etree.ElementTree as ET from .cpe import parse as parseCPE from .xml import parseDate from .. import __version__ from ..common import CVRFNote, CVRFReference from ..document import CVRF, CVRFPublisher, CVRFTracking, CVRFTrackingID, CVRFRevision, CVRFGenerator from ..producttree import CVRFFullProductName from ..utils import utcnow from ..vulnerability import CVRFVulnerability, CVRFCVSSSet, CVRFCWE, CVRFProductStatus NAMESPACES = { 'cve': "http://scap.nist.gov/schema/feed/vulnerability/2.0", 'vuln': "http://scap.nist.gov/schema/vulnerability/0.4", 'cvss': "http://scap.nist.gov/schema/cvss-v2/0.2", 'xml': "http://www.w3.org/XML/1998/namespace", } def UN(ns, name): """ returns a Universal Name """ return "{%s}%s" % (NAMESPACES[ns], name) def parseCVSS(xmlElem): """ Make a vector out of a list of elements """ def get(name): return xmlElem.findtext('/'.join([UN('cvss', 'base_metrics'), UN('cvss', name)])) cvss_set = CVRFCVSSSet(float(get('score'))) vector = [ 'AV:%s' % {'LOCAL': 'L', 'ADJACENT_NETWORK': 'A', 'NETWORK': 'N'}[get('access-vector')], 'AC:%s' % {'HIGH': 'H', 'MEDIUM': 'M', 'LOW': 'L'}[get('access-complexity')], 'Au:%s' % {'MULTIPLE': 'M', 'SINGLE': 'S', 'NONE': 'N'}[get('authentication')], 'C:%s' % {'NONE': 'N', 'PARTIAL': 'P', 'COMPLETE': 'C'}[get('confidentiality-impact')], 'I:%s' % {'NONE': 'N', 'PARTIAL': 'P', 'COMPLETE': 'C'}[get('integrity-impact')], 'A:%s' % {'NONE': 'N', 'PARTIAL': 'P', 'COMPLETE': 'C'}[get('availability-impact')], ] cvss_set.setVector('/'.join(vector)) return cvss_set def parseXML(data): """ returns am ET.Element from the input stuff. input can be: - a string - a file handle - an ET.Element instance """ if isinstance(data, ET.Element): return data # To allow passing file handles if hasattr(data, 'read'): data = data.read() # Parse it. return ET.fromstring(data) def parse_CVE_from_GSA(data): xml = parseXML(data) content = xml.find('/'.join(['get_info', 'get_info_response', 'info', 'cve', 'raw_data', UN('cve', 'entry')])) if content is None: return None return parse(content) def parse(xml): xml = parseXML(xml) # Create an extra-minimal document doc = CVRF(xml.findtext(UN('vuln', 'cve-id')), 'Vulnerability Description') pub = CVRFPublisher("Other") doc.setPublisher(pub) now = utcnow() tracking = CVRFTracking( CVRFTrackingID('000000'), "Draft", (0,), now, now ) doc.setTracking(tracking) generator = CVRFGenerator() generator.setEngine('FarolLuz ' + __version__) generator.setDate(now) tracking.setGenerator(generator) tracking.addRevision(CVRFRevision((0,), now, 'Document created')) # Add the CVE to that document return addToDoc(doc, xml) def addToDoc(doc, xml): """ Adds the CVE as vulnerability in the document """ xml = parseXML(xml) vulnid = xml.attrib['id'] # Get a new ordinal for our new Vulnerability if len(doc._vulnerabilities) == 0: ordinal = 1 else: ordinal = doc._vulnerabilities[-1]._ordinal + 1 # Create a Vulnerability vuln = CVRFVulnerability(ordinal) doc.addVulnerability(vuln) vulnerable_products = [] # Set the vulnerable products in productTree for i, cpe in enumerate(xml.findall( '/'.join([UN('vuln', 'vulnerable-software-list'), UN('vuln', 'product')]))): prod = parseCPE(cpe.text).addToDoc(doc) vulnerable_products.append(prod) if vulnerable_products: status = CVRFProductStatus('Known Affected') for product in vulnerable_products: status.addProductID(product._productid) vuln.addProductStatus(status) # Add the CVE-id vuln.setCVE(xml.findtext(UN('vuln', 'cve-id'))) # The release date vuln.setReleaseDate(parseDate(xml.findtext(UN('vuln', 'published-datetime')))) # Add the CVSS xmlcvss = xml.find(UN('vuln', 'cvss')) if xmlcvss is not None: vuln.addCVSSSet(parseCVSS(xmlcvss)) # Add the CWE id xmlcwe = xml.find(UN('vuln', 'cwe')) if xmlcwe is not None: # XXX: Get a Description for the CWE ! vuln.addCWE(CVRFCWE(xmlcwe.attrib['id'], xmlcwe.attrib['id'])) # Add references for xmlref in xml.findall(UN('vuln', 'references')): vuln.addReference(CVRFReference(xmlref.find(UN('vuln','reference')).attrib['href'], xmlref.findtext(UN('vuln', 'reference')))) xmlsummary = xml.findtext(UN('vuln', 'summary')) if xmlsummary is not None: vuln.addNote(CVRFNote( 'Summary', 1, xmlsummary )) return doc