diff farolluz/parsers/cve.py @ 43:b87f2a6e613a

Add CVE parsing (from OpenVAS GSA)
author Benoît Allard <benoit.allard@greenbone.net>
date Mon, 29 Dec 2014 16:33:34 +0100
parents
children b7e64d0a3a7c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/farolluz/parsers/cve.py	Mon Dec 29 16:33:34 2014 +0100
@@ -0,0 +1,190 @@
+# -*- 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 .xml import parseDate
+
+from ..common import CVRFNote, CVRFReference
+from ..document import CVRF, CVRFPublisher, CVRFTracking, CVRFTrackingID, CVRFRevision
+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)
+    return parse(xml.find('/'.join(['get_info', 'get_info_response', 'info', 'cve', 'raw_data', UN('cve', 'entry')])))
+
+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)
+    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')]))):
+        if doc._producttree is None:
+            doc.createProductTree()
+        try:
+            prod = doc._producttree.getProductForCPE(cpe.text)
+        except KeyError:
+            prod = CVRFFullProductName('%s-P%d' % (vulnid, i), cpe.text, doc._producttree, cpe.text)
+            doc._producttree.addProduct(prod)
+        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
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)