#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import re import math from bs4 import BeautifulSoup class CveObject: cve_no = '' # 漏洞编号 cve_nvd_url = '' # 漏洞nvd url链接地址 cve_description = '' # 漏洞描述 cve_level = '' # 威胁等级 cve_score = '' # 威胁评分 cve_cna = '' # 漏洞分配的机构 def show(self): """ Show basic vul information :return: None """ print('----------------------------------') print('编号:', self.cve_no) print('漏洞描述:', self.cve_description) print('漏洞等级:', self.cve_level) print('漏洞评分:', self.cve_score) print('\n\n') # cve search url search_url = 'https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0' } # 漏洞等级对应 level_dict = { 'CRITICAL': '严重', 'HIGH': '高', 'MEDIUM': '中', 'LOW': '低' } cve_obj_list = [] # cve obj-s fill with detailed information cve_all = [] # cve no-s fetched from nvd def fill_with_nvd(cve, cve_obj): """ Fetch detailed information by search cve to fill cve_obj that can be fetch from NVD :param cve: cve no :param cve_obj: cve object to fill :return: None """ cve_obj.cve_no = cve nvd_url = 'https://nvd.nist.gov/vuln/detail/' url = '{}{}'.format(nvd_url, cve) cve_obj.cve_nvd_url = url try: print(url) response = requests.get(url, headers=headers, timeout=60) # print(response.status_code) if response.status_code == 200: # fill description content = response.text description = re.findall('
(.*).
?', content) cve_obj.cve_description = description[0] soup = BeautifulSoup(content, "html.parser") severity = soup.find('a', id="Cvss3NistCalculatorAnchor").get_text() score, cve_level = severity.split(' ') cve_obj.cve_score = score cve_obj.cve_level = cve_level print(score, cve_level) except: print('v3 not scored, switch to v2...') severity = soup.find('a', id="Cvss2CalculatorAnchor").get_text() score, cve_level = severity.split(' ') cve_obj.cve_score = score cve_obj.cve_level = cve_level print(score, cve_level) finally: pass pass def fetch_all_cves(producer, software, banner): """ Query NVD to get specific version of software vulnerabilities :return: None """ # contruct query string if banner: keyword = '{}%3a{}'.format(software, banner) else: keyword = software url = 'https://nvd.nist.gov/vuln/search/results?form_type=Advanced&' \ 'cves=on&cpe_version=cpe%3a%2fa%3a{}%3a{}'.format(producer, keyword) print(url) # to get cve number try: response = requests.get(url, timeout=60, headers=headers) if response.status_code == 200: num = re.findall('"vuln-matching-records-count">(.*)?', response.text)[0] msg = 'There are {} cves with {} {}...'.format(num, software, banner) print(msg) except: pass # fetch all cve no start_index = index = 0 while start_index < int(num): url = 'https://nvd.nist.gov/vuln/search/results?form_type=Advanced&' \ 'cves=on&cpe_version=cpe%3a%2fa%3a{}%3a{}&' \ 'startIndex={}'.format(producer, keyword, start_index) msg = 'processing page {}/{}...'.format(index+1, math.ceil(int(num) / 20)) print(msg) index += 1 start_index = index * 20 try: response = requests.get(url, timeout=60, headers=headers) if response.status_code == 200: cves = re.findall('"vuln-detail-link-\d+">(.*)?', response.text) cve_all.extend(cves) except: pass print('\n-------- CVEs ---------\n') for line in cve_all: print(line) print() def fetch_vul_info(producer, software, banner): # get all cves fetch_all_cves(producer, software, banner) i = 0 for cve in cve_all: i += 1 cve_obj = CveObject() # if i == 4: # break msg = '[{}/{}] Fetching {} ...'.format(i, cve_all.__len__(), cve) print(msg) # fill cve object with information from nvd fill_with_nvd(cve, cve_obj) cve_obj_list.append(cve_obj) pass def save_cve_objs(): """ Save cve info to a file :return: None """ for obj in cve_obj_list: cve_info = '{}|{}|{}|{}|{}|{}\n'.format(obj.cve_no, obj.cve_nvd_url, obj.cve_score, obj.cve_level, obj.cve_cna, obj.cve_description) # with open('cve.txt', 'a+') as fw: # fw.write(cve_info) def write2html(): """ Write cve into to create a html file, this function is terriblely implemented, (^_^) :param keyword: software name :return: None """ print('write data to html') html = '' header = '\ \ \| 等级 | \严重 | \高危 | \中危 | \低危 | \
| 个数({}) | \{} | \{} | \{} | \{} | \