Mercurial > farol > farolluz
view 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 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 .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