需求分析
周末,接到通知,要为某单位临时添加一批规则,规则开发完毕之后,填写到规则库平台的时候,需要填写漏洞编号,中英文漏洞标题,中英文漏洞描述,参考链接。由于所在部门不能直接连接互联网,因此,如果通过云桌面的形式间接添加漏洞规则相关信息,会很麻烦。
期望:我只提供给你漏洞编号,你能反馈给我:漏洞编号,中英文漏洞标题,中英文漏洞描述,参考链接等信息
我这里提供两个脚本:
第一个是爬取安全客,缺点是漏洞信息较少,优点是容易爬取
第二个是国家信息安全漏洞库,缺点是不敢爬,网站偶尔会无法访问,优点是漏洞信息更全面
源代码-1
脚本会根据你的漏洞编号去安全客上搜索相关漏洞信息(安全客镜像了国家漏洞信息库的漏洞信息),然后借助有道翻译给出中英文信息。脚本直接运行即可,无需做任何修改。
- 支持CVE和CNNVD两种漏洞编号
- 终端中会打印结果,并且会把结果保存到你的桌面
- 目前已知有些中文漏洞描述信息不能被完整的翻译成英文,暂时没去分析有道的处理逻辑
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
脚本直接运行,无需更改。
- 支持CVE和CNNVD两种漏洞编号
- 终端中会打印结果,并且会把结果保存到你的桌面
- 目前已知有些中文漏洞描述信息不能被完整的翻译成英文,暂时没去分析有道的处理逻辑
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()
效果展示
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/134271.html