diff --git a/README.md b/README.md index 988069a..5ab2e4f 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,49 @@ ## 更新日志 -### 2020.1.18 -内容:修改脚本以适应NVD界面变化 & cvss v3未评分异常。 +`2022.3.29` `add` `search_vuls.py` -增加脚本:script-v2.1.py 和 script-v3.1.py +`2020.1.18` `modify` `script-v2.py & script-v3.py` +`修改脚本以适应NVD界面变化 & cvss v3未评分异常。` +## search_vuls.py +搜索特定软件,获取其所有漏洞,以列表的形式给出,便于手工按照漏洞优先级逐一排查。 + +``` +python3 search_vuls.py +please input which sofware you want to search vuls ... +=> kong +[*] checking https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=kong ... +[+] => ['CVE-2021-32753', 'CVE-2021-27306', 'CVE-2020-35189', 'CVE-2020-11710', 'CVE-2018-0269', 'CVE-2014-7057'] +[*] task qsize => 6 +[2] fetch ... https://nvd.nist.gov/vuln/detail/CVE-2021-27306 +[1] fetch ... https://nvd.nist.gov/vuln/detail/CVE-2021-32753 +[3] fetch ... https://nvd.nist.gov/vuln/detail/CVE-2020-35189 +[4] fetch ... https://nvd.nist.gov/vuln/detail/CVE-2020-11710 +[5] fetch ... https://nvd.nist.gov/vuln/detail/CVE-2018-0269 +[6] fetch ... https://nvd.nist.gov/vuln/detail/CVE-2014-7057 +v3 not scored, switch to v2... ++-----+----------------+-------+----------+-------------------------------------------------+ +| No. | CVE | Score | Level | URL | ++-----+----------------+-------+----------+-------------------------------------------------+ +| 1 | CVE-2018-0269 | 4.3 | MEDIUM | https://nvd.nist.gov/vuln/detail/CVE-2018-0269 | +| 2 | CVE-2020-35189 | 9.8 | CRITICAL | https://nvd.nist.gov/vuln/detail/CVE-2020-35189 | +| 3 | CVE-2021-32753 | 6.5 | MEDIUM | https://nvd.nist.gov/vuln/detail/CVE-2021-32753 | +| 4 | CVE-2021-27306 | 7.5 | HIGH | https://nvd.nist.gov/vuln/detail/CVE-2021-27306 | +| 5 | CVE-2020-11710 | 9.8 | CRITICAL | https://nvd.nist.gov/vuln/detail/CVE-2020-11710 | +| 6 | CVE-2014-7057 | 5.4 | MEDIUM | https://nvd.nist.gov/vuln/detail/CVE-2014-7057 | ++-----+----------------+-------+----------+-------------------------------------------------+ +It costs 9 seconds to run the task +``` +## Sample - v3 + +update:2020.1.3 + +获取某个软件版本的漏洞总览信息,包括:漏洞个数,严重、高危、中危、低危漏洞个数,漏洞描述等必要信息,及CVE的漏洞等级情况,并以html的形式展现。 + +A script to get vulnerabilities of specific software version, which contains vul number, vul level, vul description, and CVE no vul level, and present with html. + + ## Sample - v2 @@ -45,16 +83,6 @@ CVE-2011-1503 - 低 CVE-2011-1502 - 中 ``` -## Sample - v3 - -update:2020.1.3 - -获取某个软件版本的漏洞总览信息,包括:漏洞个数,严重、高危、中危、低危漏洞个数,漏洞描述等必要信息,及CVE的漏洞等级情况,并以html的形式展现。 - -A script to get vulnerabilities of specific software version, which contains vul number, vul level, vul description, and CVE no vul level, and present with html. - - - ## Sample - v1 update: outdated diff --git a/search_vuls.py b/search_vuls.py new file mode 100644 index 0000000..8a3998e --- /dev/null +++ b/search_vuls.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @Time : 2022/3/28 +# @Author : starnight_cyber +# @Github : https://github.com/starnightcyber +# @Software: PyCharm +# @File : search_vuls.py + +import datetime +from queue import Queue +from multiprocessing import Pool +import requests +import ssl +import time +import re +from requests.packages.urllib3.exceptions import InsecureRequestWarning +from bs4 import BeautifulSoup +from prettytable import PrettyTable + +# Do not support ssl and disable warning +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +ssl._create_default_https_context = ssl._create_unverified_context +timestamp = time.strftime("%Y-%m-%d", time.localtime(time.time())) + +headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36' +} + +task_queue = Queue() +process_num = 10 +services_info = [] +total_tasks = [] +cve_obj_list = [] # cve obj-s fill with detailed information + + +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') + + +def worker(cve, index): + """ + 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 = CveObject() + cve_obj.cve_no = cve + + nvd_url = 'https://nvd.nist.gov/vuln/detail/' + url = '{}{}'.format(nvd_url, cve) + print('[{}] fetch ... {}'.format(index, url)) + + cve_obj.cve_nvd_url = url + try: + resp = requests.get(url=url, headers=headers, timeout=30, verify=False) + if resp.status_code == 200: + content = resp.text + # print('content => {}'.format(content)) + description = re.findall('
(.*).
?', content) + cve_obj.cve_description = description[0] + # print('cve_obj.cve_description => {}'.format(cve_obj.cve_description)) + + 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: + return cve_obj + pass + + +def setcallback(cve_obj): + if cve_obj: + cve_obj_list.append(cve_obj) + + +def run_engine(): + pool = Pool(process_num) # 创建进程池 + index = 0 + while not task_queue.empty(): + index += 1 + task = task_queue.get(timeout=1.0) + pool.apply_async(worker, args=(task, index), callback=setcallback) + pool.close() + pool.join() + + +def search_vuls(software): + url = 'https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword={}'.format(software) + print('[*] checking {} ...'.format(url)) + try: + resp = requests.get(url=url, headers=headers, timeout=10, verify=False) + if resp.status_code == 200: + tmp = re.findall('/cgi-bin/cvename.cgi\?name=(.*)?">', resp.text) + print('[+] => {}'.format(tmp)) + for cve in tmp: + task_queue.put(cve) + print('[*] task qsize => {}'.format(task_queue.qsize())) + except Exception as e: + print(str(e)) + pass + finally: + pass + + +def pretty_print(): + global cve_obj_list + t = PrettyTable(['No.', 'CVE', 'Score', 'Level', 'URL']) + index = 0 + for cve_obj in cve_obj_list: + index += 1 + row = [index, cve_obj.cve_no, cve_obj.cve_score, cve_obj.cve_level, cve_obj.cve_nvd_url] + t.add_row(row) + print(t) + + +def main(): + # tips + software = input('please input which sofware you want to search vuls ... \n\r=> ') + # search vuls + search_vuls(software) + # parallel scan engine + run_engine() + # pretty print + pretty_print() + + +if __name__ == '__main__': + start = datetime.datetime.now() + main() + end = datetime.datetime.now() + spend_time = (end - start).seconds + msg = 'It costs {} seconds to run the task'.format(spend_time) + print(msg)