规则库捕获漏洞信息专用脚本

需求分析

周末,接到通知,要为某单位临时添加一批规则,规则开发完毕之后,填写到规则库平台的时候,需要填写漏洞编号,中英文漏洞标题,中英文漏洞描述,参考链接。由于所在部门不能直接连接互联网,因此,如果通过云桌面的形式间接添加漏洞规则相关信息,会很麻烦。

期望:我只提供给你漏洞编号,你能反馈给我:漏洞编号,中英文漏洞标题,中英文漏洞描述,参考链接等信息

我这里提供两个脚本:
第一个是爬取安全客,缺点是漏洞信息较少,优点是容易爬取
第二个是国家信息安全漏洞库,缺点是不敢爬,网站偶尔会无法访问,优点是漏洞信息更全面

源代码-1

脚本会根据你的漏洞编号去安全客上搜索相关漏洞信息(安全客镜像了国家漏洞信息库的漏洞信息),然后借助有道翻译给出中英文信息。脚本直接运行即可,无需做任何修改。

  1. 支持CVE和CNNVD两种漏洞编号
  2. 终端中会打印结果,并且会把结果保存到你的桌面
  3. 目前已知有些中文漏洞描述信息不能被完整的翻译成英文,暂时没去分析有道的处理逻辑
from lxml import etree
import json
import requests
import re
import os

'''
脚本功能:
根据批量提交的漏洞编号(cve、cnnvd),获取其中英文漏洞标题,中英文漏洞描述
并将其写入到Excel表中
'''


# 下面三个函数用来实现翻译效果
# 翻译函数,word 需要翻译的内容
def translate(word):
    # 有道词典 api
    url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null'
    # 传输的参数,其中 i 为需要翻译的内容
    key = {
        'type': "AUTO",
        'i': word,
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "ue": "UTF-8",
        "action": "FY_BY_CLICKBUTTON",
        "typoResult": "true"
    }
    # key 这个字典为发送给有道词典服务器的内容
    response = requests.post(url, data=key)
    # 判断服务器是否相应成功
    if response.status_code == 200:
        # 然后相应的结果
        return response.text
    else:
        print("有道词典调用失败")
        # 相应失败就返回空
        return None


def get_reuslt(repsonse):
    # 通过 json.loads 把返回的结果加载成 json 格式
    result = json.loads(repsonse)
    # print("输入的词为:%s" % result['translateResult'][0][0]['src'])
    # print("翻译结果为:%s" % result['translateResult'][0][0]['tgt'])
    return result['translateResult'][0][0]['tgt']


def you_dao_translation(translation_word):
    # print("本程序调用有道词典的API进行翻译,可达到以下效果:")
    # print("外文-->中文")
    # print("中文-->英文")
    word = translation_word
    list_trans = translate(word)
    return get_reuslt(list_trans)


# 用来访问安全客,获取漏洞标题和漏洞描述,并将其写入到Excel表中
def get_anquanke(vul_id):
    vul_number = vul_id
    url = "https://api.anquanke.com/data/v1/search/vul?s=" + vul_number + "&c=&field=&start=&end=&c=&platform="
    resp = requests.get(url)

    a = resp.text
    if len(a) == 54:
        print('此漏洞编号,安全客中不存在')
    else:
        print(vul_number)
        result.append(vul_number)
        b = re.findall('\x22id\x22\x3a\x22\d+\x22', a)
        c = ''  # 用来存储cnnvd、cve对应的安全客里面的id号
        for i in b:
            c = i.split(':')[-1].strip('"')

        url1 = "https://www.anquanke.com/vul/id/" + c
        resp1 = requests.get(url1)

        # 解析
        html = etree.HTML(resp1.text)

        # 提取出漏洞名称
        divs1 = html.xpath("/html/body/main/div/div/div/div[1]/div[1]/h1/text()")
        for i in divs1:
            b = i.split('\n')
            for ii in b:
                if '漏洞' in ii:
                    print(ii.strip())
                    print(you_dao_translation(ii.strip()))
                    result.append(ii.strip())
                    result.append(you_dao_translation(ii.strip()))

        # 提取漏洞详情
        divs2 = html.xpath("/html/body/main/div/div/div/div[1]/div[3]/div/text()")
        c = []
        for i in divs2:
            b = i.split('\n')
            for ii in b:
                # print(ii.strip())
                c.append(ii.strip())
        # 由于有道翻译会截断句号,下面的操作就是把漏洞描述的句号全部替换为逗号,再把最后一个结尾的逗号修改为句号
        d = ''.join(c)
        d1 = d.replace('。', ',')
        d2 = d1.rsplit(',', 1)
        d2.append('。')
        d3 = ''.join(d2)
        print(d3)
        print(you_dao_translation(d3))
        result.append(d3)
        result.append(you_dao_translation(d))

        print(url1)
        result.append(url1)
        print()
        result.append('')  # 充当换行符


print("请输入漏洞编号,可以是CVE编号或者CNNVD编号(输入quit结束输入):")
result = []  # 将获取到的中英文漏洞名称、漏洞标题放到列表中,方便后期使用
desktop_path = os.path.join(os.path.expanduser("~"), 'Desktop')
path1 = os.path.join(desktop_path, '漏洞信息.txt')

word = []  # 存储用户输入的内容
while True:
    char = input()
    char = char.strip()
    # 下面的两个if主要是判断输入的内容中是否:某行是空白,某行用逗号分割了字符串(主要适用于多个tid)
    if char == '':
        continue
    if 'quit' in char:
        break
    word.append(char)

for i in word:
    get_anquanke(i)

# 下面的代码用来把终端中的内容输出到一个文本中
write_result = open(path1, 'w', encoding='utf8')
for r in result:
    write_result.write(r)
    write_result.write('\n')
write_result.close()

# os.system('pause')  # 在脚本中运行时可以删除此行

效果展示

在这里插入图片描述

源代码-2

脚本直接运行,无需更改。

  1. 支持CVE和CNNVD两种漏洞编号
  2. 终端中会打印结果,并且会把结果保存到你的桌面
  3. 目前已知有些中文漏洞描述信息不能被完整的翻译成英文,暂时没去分析有道的处理逻辑
from lxml import etree
import json
import requests
import re
import os
import csv

'''
纯爬虫脚本:爬取“国家信息安全漏洞库”
'''


# 下面三个函数用来实现翻译效果
# 翻译函数,word 需要翻译的内容
def translate(word):
    # 有道词典 api
    url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null'
    # 传输的参数,其中 i 为需要翻译的内容
    key = {
        'type': "AUTO",
        'i': word,
        "doctype": "json",
        "version": "2.1",
        "keyfrom": "fanyi.web",
        "ue": "UTF-8",
        "action": "FY_BY_CLICKBUTTON",
        "typoResult": "true"
    }
    # key 这个字典为发送给有道词典服务器的内容
    response = requests.post(url, data=key)
    # 判断服务器是否相应成功
    if response.status_code == 200:
        # 然后相应的结果
        return response.text
    else:
        print("有道词典调用失败")
        # 相应失败就返回空
        return None


def get_reuslt(repsonse):
    # 通过 json.loads 把返回的结果加载成 json 格式
    result = json.loads(repsonse)
    # print("输入的词为:%s" % result['translateResult'][0][0]['src'])
    # print("翻译结果为:%s" % result['translateResult'][0][0]['tgt'])
    return result['translateResult'][0][0]['tgt']


def you_dao_translation(translation_word):
    # print("本程序调用有道词典的API进行翻译,可达到以下效果:")
    # print("外文-->中文")
    # print("中文-->英文")
    word = translation_word
    list_trans = translate(word)
    return get_reuslt(list_trans)


# 用来访问国家信息安全漏洞库
def get_CNNVD(vul_id):
    cnnvd_id = ''
    '''
    下面的每种变量都设了两次,是做如下考虑,举个例子:
    ”result_cnnvd“输出"CVE编号:CVE-2020-25683",直接打印在终端,输出到格式1的txt文本的结果中
    ”result_cnnvd1“输出"CVE-2020-25683",直接输出到csv结果中,输出到格式2的txt文本的结果中。这样的txt文本方便复制粘贴,是个人使用的。
    '''
    result_cnnvd = ''  # 终端中打印的(并写在TXT文本中的):"CVE编号:CVE-2020-25683"
    result_cnnvd1 = ''  # 写在CSV中的,如:"CVE-2020-25683"
    result_cve = ''  # cve编号
    result_cve1 = ''
    result_harm = ''  # 危害等级
    result_harm1 = ''
    result_vul_type = ''  # 漏洞类型
    result_vul_type1 = ''
    result_title_zh = ''  # 中文漏洞标题
    result_title_zh1 = ''
    result_title_en = ''  # 英文漏洞标题
    result_title_en1 = ''
    result_describe_zh = ''  # 中文漏洞描述
    result_describe_zh1 = ''
    result_describe_en = ''  # 英文漏洞描述
    result_describe_en1 = ''
    result_notice = ''  # 漏洞公告
    result_link = ''  # 公告参考地址

    # 如果输入的是cnnvd编号,直接pass;否则就访问安全客,获取其cnnvd编号。拿着cnnvd编号访问国家信息安全漏洞库
    # 这么做的原因(举个例子):如果用户输入cve-2021-2112,那么对应的漏洞位于第2页;如果输入对应的cnnvd编号,则直接获取到对应漏洞位置

    if "cnnvd" in vul_id.lower():
        pass
    else:
        url = "https://api.anquanke.com/data/v1/search/vul?s=" + vul_id + "&c=&field=&start=&end=&c=&platform="
        resp_aqk = requests.get(url).text
        if len(resp_aqk) == 54:
            print('CVE漏洞编号不存在')
        else:
            b = re.findall('\x22id\x22\x3a\x22\d+\x22', resp_aqk)
            c = ''  # 用来存储cnnvd、cve对应的安全客里面的id号
            for i in b:
                c = i.split(':')[-1].strip('"')

            url1 = "https://www.anquanke.com/vul/id/" + c
            resp1 = requests.get(url1)
            html = etree.HTML(resp1.text)

            divs1_aqk = html.xpath("/html/body/main/div/div/div/div[1]/div[1]/div[2]/table/tbody/tr[3]/td[4]/text()")
            for i in divs1_aqk:
                vul_id = i

    # 获取“漏洞信息”网页
    resp = requests.post(
        url="http://www.cnnvd.org.cn/web/vulnerability/queryLds.tag",
        headers={
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
            'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
            'Accept-Language': "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            'Content-Type': "application/x-www-form-urlencoded",
            "Origin": "http://www.cnnvd.org.cn",  # 伪装绕过
            "Referer": "http://www.cnnvd.org.cn/web/vulnerability/querylist.tag",
            'Cookie': "SESSION=755075bc-a8d4-4471-b048-cc1e5f5824a9; topcookie=a1",
            'Upgrade-Insecure-Requests': '1'
        },
        data='''CSRFToken=&cvHazardRating=&cvVultype=&qstartdateXq=&cvUsedStyle=&cvCnnvdUpdatedateXq=&cpvendor=&relLdKey=&hotLd=&isArea=&qcvCname=&qcvCnnvdid=''' + vul_id + '&qstartdate=&qenddate='
    )

    result = resp.text
    if "CNNVD=CNNVD" not in result:
        print('你输入的漏洞编号不存在!')
    else:
        b = re.findall('CNNVD=CNNVD-\d+-\d+', result)
        cnnvd_id = b[0].split('=')[-1]  # 提取出cnnvd的漏洞编号

    # 获取“漏洞信息详情”网页
    url1 = "http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=" + cnnvd_id
    resp1 = requests.get(
        url1,
        headers={
            'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36",
            'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
            'Accept-Language': "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Referer": "http://www.cnnvd.org.cn/web/vulnerability/querylist.tag",
            'Cookie': "SESSION=755075bc-a8d4-4471-b048-cc1e5f5824a9; topcookie=a1",
            'Upgrade-Insecure-Requests': '1'
        })

    # 解析
    html = etree.HTML(resp1.text)

    # 提取出“CNNVD编号”
    divs1 = html.xpath("/html/body/div[4]/div/div[1]/div[2]/ul/li[1]/span/text()")
    for i in divs1:
        result_cnnvd1 = i.split(':')[-1]
        result_cnnvd = "CNNVD编号:" + result_cnnvd1
        print(result_cnnvd)
        give_result.append(result_cnnvd)
        give_result1.append(result_cnnvd1)

    # 提取出“CVE编号”
    divs2 = html.xpath("/html/body/div[4]/div/div[1]/div[2]/ul/li[3]/a/text()")
    for i in divs2:
        result_cve1 = i.split('\n')[0].split(' ')[-1]
        if len(result_cve1) > 4:  # 判断一下cve编号是否存在
            result_cve = "CVE编号:" + result_cve1
            print(result_cve)  # 打印出CVE编号
            give_result.append(result_cve)
            give_result1.append(result_cve1)
        else:
            result_cve1 = '无'
            result_cve = 'CVE编号:' + result_cve1
            print(result_cve)
            give_result.append(result_cve)
            give_result1.append(result_cve1)

    # 提取出“危害等级”
    divs3 = html.xpath("/html/body/div[4]/div/div[1]/div[2]/ul/li[2]/a/text()")
    divs3 = str(divs3)
    reg = "[^\u4e00-\u9fa5]"  # 使用正则提取出中文
    result_harm1 = re.sub(reg, '', divs3)
    result_harm = '危害等级:' + result_harm1
    print(result_harm)
    give_result.append(result_harm)
    give_result1.append(result_harm1)

    # 提取出“漏洞类型”
    divs4 = html.xpath("/html/body/div[4]/div/div[1]/div[2]/ul/li[4]/a/text()")
    divs4 = str(divs4)
    reg = "[^\u4e00-\u9fa5]"  # 使用正则提取出中文
    result_vul_type1 = re.sub(reg, '', divs4)
    result_vul_type = '漏洞类型:' + result_vul_type1
    print(result_vul_type)
    give_result.append(result_vul_type)
    give_result1.append(result_vul_type1)

    # 提取出”漏洞标题“
    divs5 = html.xpath("/html/body/div[4]/div/div[1]/div[2]/h2/text()")
    for i in divs5:
        result_title_zh1 = i.split('\n')[0]
        result_title_en1 = you_dao_translation(result_title_zh1)
        result_title_zh = '中文漏洞标题:' + result_title_zh1
        result_title_en = '英文漏洞标题:' + result_title_en1
        print(result_title_zh)  # 打印出中文漏洞标题
        print(result_title_en)  # 打印英文漏洞标题
        give_result.append(result_title_zh)
        give_result1.append(result_title_zh1)
        give_result.append(result_title_en)
        give_result1.append(result_title_en1)

    # 提取”漏洞描述“
    divs6 = html.xpath("/html/body/div[4]/div/div[1]/div[3]/p/text()")
    divs6 = str(divs6)
    # 提取出漏洞描述,并删除所有的句号(防止有道翻译截断),最后在漏洞描述的文末添加句号表示结束
    if ',' in divs6:  # 判断漏洞描述究竟是一个自然段还是两段自然段
        a1 = divs6.replace('[', '').replace(']', '').replace(r'\n', '')
        a1 = a1.replace(r'\t', '').replace("'", '').replace('。', ',').replace(',', '')
    else:
        a1 = divs6.replace('[', '').replace(']', '').replace(r'\n', '')
        a1 = a1.replace(r'\t', '').replace("'", '').replace('。', ',')

    a2 = a1.rsplit(',', 1)
    a2[-1] = '。'
    result_describe_zh1 = ''.join(a2)
    result_describe_en1 = you_dao_translation(result_describe_zh1)
    result_describe_zh = '中文漏洞描述:' + result_describe_zh1
    result_describe_en = '英文漏洞描述:' + result_describe_en1
    print(result_describe_zh)  # 打印中文漏洞描述
    print(result_describe_en)  # 打印英文漏洞描述
    give_result.append(result_describe_zh)
    give_result1.append(result_describe_zh1)
    give_result.append(result_describe_en)
    give_result1.append(result_describe_en1)

    # 提取出漏洞公告中的地址
    divs7 = str(html.xpath("/html/body/div[4]/div/div[1]/div[4]/p[2]/text()"))
    result_link = divs7.split(r'\n')[1]

    # 提取”漏洞公告“
    divs8 = str(html.xpath("/html/body/div[4]/div/div[1]/div[4]/p[1]/text()"))
    if "已发布" in divs8:
        result_notice = '漏洞已修复,补丁获取链接:' + result_link
    else:
        result_notice = '漏洞未修复,请关注厂商地址:' + result_link
    print(result_notice)
    give_result.append(result_notice)

    print()
    give_result.append('')
    give_result1.append('')

    write.writerow([result_cnnvd1, result_cve1, result_harm1, result_vul_type1, result_title_zh1, result_title_en1,
                    result_describe_zh1, result_describe_en1, result_notice, url1])


# 导出txt结果
def result_txt():
    file_txt = open(path1, 'w', encoding='utf8')
    for r in give_result:
        file_txt.write(r)
        file_txt.write('\n')
    file_txt.close()

    file_txt1 = open(path2, 'w', encoding='utf8')
    for r in give_result1:
        file_txt1.write(r)
        file_txt1.write('\n')
    file_txt1.close()


if __name__ == '__main__':
    give_result = []  # 用来存储漏洞相关信息
    give_result1 = []  # 用来存储漏洞相关信息-简洁版
    desktop_path = os.path.join(os.path.expanduser("~"), 'Desktop')
    path1 = os.path.join(desktop_path, '漏洞信息.txt')  # 给出txt格式的结果,方便复制粘贴,写到平台上
    path2 = os.path.join(desktop_path, '漏洞信息-简洁版.txt')  # 给出txt格式的结果,方便复制粘贴,写到平台上
    path3 = os.path.join(desktop_path, '漏洞信息.csv')  # 给出csv格式的结果,方便展示
    print("请输入漏洞编号,可以是CVE编号或者CNNVD编号(输入quit结束输入):")

    word = []  # 存储用户输入的内容
    while True:
        char = input()
        char = char.strip()
        # 下面的两个if主要是判断输入的内容中是否:某行是空白,某行用逗号分割了字符串(主要适用于多个tid)
        if char == '':
            continue
        if 'quit' in char:
            break
        word.append(char)

    file = open(path3, 'w', newline='')  # 创建并打开CSV文件
    write = csv.writer(file)
    write.writerow(['CNNVD编号', 'CVE编号', '危害等级', '漏洞类型', '中文漏洞标题', '英文漏洞标题', '中文漏洞描述', '英文漏洞描述', '漏洞公告', '漏洞参考地址'])

    for i in word:
        get_CNNVD(i)
    file.close()

    result_txt()

效果展示

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值