(ネタをパクりました。大変申し訳ございません。)
(CVEの番号から適当にCVSS v3のスコアを取ってくる | hacknote のPython版です。)
(CVEの識別子を与えると、NVDのページからCVSS V3 Base Score を取得してくるやつです。)
#!/usr/bin/env python # -*- coding: utf-8 -*- from StringIO import StringIO from lxml import etree import urllib3 import sys import certifi import re class Foo: __NVD_DETAIL_URL = "https://web.nvd.nist.gov/view/vuln/detail?vulnId=%s" __CVSS_V3_SCORE_XPATH = '//div[@class="row" and contains(./span[@class="label"]/text(), "CVSS v3 Base Score")]/a/text()' __CVSS_V3_RATING_XPATH = '//div[@class="row" and contains(./span[@class="label"]/text(), "CVSS v3 Base Score")]/text()' u""" CVSS v3 Base Score 取得 """ @classmethod def extractCvssV3Score(cls, cve_id): # NVDの脆弱性詳細ページ取得 url = cls.__NVD_DETAIL_URL % cve_id response = urllib3.PoolManager( cert_reqs = 'CERT_REQUIRED', ca_certs = certifi.where() ).request('GET', url).data f = StringIO(response) parser = etree.HTMLParser() doc = etree.parse(f, parser) # score (x.x) scores = doc.xpath(cls.__CVSS_V3_SCORE_XPATH) if len(scores) != 1: raise Exception("failed to extract cvss v3 score") score = scores[0] # rating (Critical High...) rating = None ratings = doc.xpath(cls.__CVSS_V3_RATING_XPATH) # 空白文字だけのゴミが含まれるため rating_pattern = r"^\s*(\S+)\s*$" for e in ratings: m = re.match(rating_pattern, e) if m: rating = m.group(1) break if not rating: raise Exception("failed to extract cvss v3 rating") return (score.strip(), rating.strip())
$ python python> from xxx import Foo python> Foo.extractCvssV3Score("CVE-2016-3074") => returns ('9.8', 'Critical')