公司做系统集成,有搜集产品脆弱性需求,包括cisco,vmware,redhat,F5等厂家。
具体需求:
1.每天定时搜集十来个网络设备厂家网站新发布的脆弱性
2.根据产品和等级不同,邮件发给不同公司人员,内容包括:新脆弱性链接,脆弱性标题,CVE编号,发布时间等
2.不能发送重复脆弱性内容
难点:F5和ivanti网站遇到JWT问题,认证包含多次js的跳转(checkbox点选后),每次拿到的token有效期只有一天,思路是提前访问网站拿一下token,再带着有效token访问数据,这个看起来很困难,其实一点也不简单。
分析产品网站,通过xhr找到对应级别脆弱性的数据接口链接,response是一个大的json串
1.导入相关package,定义当天和昨天时间,因为大厂基本都是utc时间发布,仅检查当天即使是23:59检查也没用,中国时间看网站还没发布,utc时间发布后转换回来是中国的昨天时间###。
时间转换参考网站格式,用于比对判断。
import requests
import json
import datetime
today = datetime.date.today()
format_today=today.strftime("%Y-%m-%d")
yesterday = today - datetime.timedelta(days=1)
format_yesterday=yesterday.strftime("%Y-%m-%d")
url_cisco='xxx'
response=requests.get(url_cisco)
found_string=f"there WAS new vulnerability {format_today}"
nofound_string=f"No new vulnerability {format_today} "
filename=f"xxx.txt"
2. 判断脆弱性函数,并记录到文件,根据特征字段判断是否已经通知过,避免重复###
def getCiscoVulnerability(url_cisco):
sendmail.has_been_called = False
for item in response.json():
lastPublished=item["lastPublished"]
if (lastPublished==format_today and astPublished not in filename) or (lastPublished==format_yesterday and and lastPublished not in filename):
url_cisco = item["url"]
title_cisco = item["title"]
cve_cisco = item["cve"]
summary_cisco = item["summary"]
vul_date=lastPublished
list=["思科产品:",title_cisco,summary_cisco,cve_cisco,vul_date,url_cisco]
sendmail(url_cisco, title_cisco, summary_cisco, cve_cisco, vul_date)
with open(filename, 'a') as file:
file.write("\n")
file.writelines("\t".join(list))
else:
continue
#根据发邮件函数调用与否,判断是否有新增脆弱性并记录日志
if sendmail.has_been_called:
print(found_string)
else:
print(nofound_string)
3. 发邮件模块
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
def sendmail(url_cisco,title_cisco,summary_cisco,cve_cisco,vul_date):
sendmail.has_been_called = True
# 设置发件人,收件人,主题和内容
sender = 'xxx'
receivers = ['xxx']
subject = 'xxx'
body = f"xxx"
# 创建邮件对象
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = ', '.join(receivers)
msg['Subject'] = subject
msg.attach(MIMEText(body))
# 连接到SMTP服务器,发送邮件
smtp_server = 'xx'
smtp_port = 25 # 通常为587或465
smtp_username = 'xx' # 如果需要用户名和密码登录SMTP服务器,请提供用户名和密码。如果不需要,可以忽略此行。
smtp_password = 'xx' # 如果需要用户名和密码登录SMTP服务器,请提供用户名和密码。如果不需要,可以忽略此行。
try:
with smtplib.SMTP(smtp_server, smtp_port) as server:
# server.starttls() # 开始TLS加密会话,这通常在连接时进行。如果你使用的SMTP服务器不支持TLS加密,你可能需要联系你的邮件服务提供商。
if smtp_username and smtp_password:
server.login(smtp_username, smtp_password) # 如果SMTP服务器需要用户名和密码登录,请提供用户名和密码。如果不需要,可以忽略此行。
server.sendmail(sender, receivers, msg.as_string()) # 发送邮件
except Exception as e:
print(f"Error: {e}")
#主函数调用查找判断
def main():
getCiscoVulnerability(url_cisco)
main()
其他产品网站类似,有的用到xpath或bs4,有的要拿到二级链接再次查找后判断,思路大同小异。
JWT的部分,后来仔细分析了一下URL获取情况已经搞定了,找到实际获取token的URL即可。
后来根据同事建议,做了一个小的GUI工具,可以手动直观的检查一下,需要注意的是:
1. 多条脆弱性需要分别append到列表,最后join处理成字符串,再return出来;
2. 由于critical和high等对应不同链接,实际使用要根据需求分别循环找一下。
工具主要代码:
import vul_detect import wx import wx.xrc import wx.grid from tkinter import messagebox class MyFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, -1, "产品脆弱性检测",size=(600, 400)) icon = wx.Icon("./1.ico", wx.BITMAP_TYPE_ICO) self.SetIcon(icon) panel = wx.Panel(self) # 创建单选框 self.radio1 = wx.RadioButton(panel, label="cisco", pos=(20, 20)) self.radio2 = wx.RadioButton(panel, label="redhat", pos=(20, 50)) self.radio3 = wx.RadioButton(panel, label="vmware", pos=(20, 80)) self.radio4 = wx.RadioButton(panel, label="paloalto", pos=(20, 110)) self.radio5 = wx.RadioButton(panel, label="checkpoint", pos=(20, 140)) self.btn1 = wx.Button(panel, label="检测脆弱性", pos=(20, 160),size=(80,40)) # 创建多行文本框 self.multi_text = wx.TextCtrl(panel, style=wx.TE_MULTILINE,pos=(200, 600),size=(400,600)) # self.multi_text = wx.TextCtrl(panel, style=wx.TE_READONLY,pos=(20, 500)) self.multi_text.SetValue("Hello, wxFormBuilder!") ##wx.TextCtrl被创建时设置了wx.TE_MULTILINE样式,使得文本框可以接受多行输入。wx.BoxSizer用于管理文本框的布局,wx.ALL|wx.EXPAND确保文本框会填充它的父容器。 # 布局文本框 sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.multi_text, 1, wx.ALL | wx.EXPAND, 100) panel.SetSizer(sizer) # 将单选框分组,将它们放入同一个分组中。这意味着在同一时间只有一个单选框可以被选中 self.radio1.SetName("RadioGroup") self.radio2.SetName("RadioGroup") self.radio3.SetName("RadioGroup") self.radio4.SetName("RadioGroup") self.radio5.SetName("RadioGroup") self.Bind(wx.EVT_BUTTON, self.OnButton1, self.btn1) # self.SetSize((600, 400)) # self.Centre() def OnButton1(self, event): if self.radio1.GetValue(): cisco = vul_detect.cisco() self.multi_text.SetValue(cisco) elif self.radio2.GetValue(): redhat = vul_detect.redhat() self.multi_text.SetValue(str(redhat)) else: messagebox.showinfo("未选择产品","请选择一个要检查脆弱性的厂家") class MyApp(wx.App): def OnInit(self): self.frame = MyFrame(None) self.frame.Show() self.SetTopWindow(self.frame) return True if __name__ == "__main__": app = MyApp(0) app.MainLoop()
---------
vul_detect代码:
import requests import datetime def cisco(): today = datetime.date.today() format_today = today.strftime("%Y-%m-%d") yesterday = today - datetime.timedelta(days=1) format_yesterday = yesterday.strftime("%Y-%m-%d") cisco_list = [] url_cisco = 'https://sec.cloudapps.cisco.com/security/center/publicationService.x?criteria=exact&cves=&keyword=&last_published_date=&limit=20&offset=0&publicationTypeIDs=1,3&securityImpactRatings=high&sort=-day_sir&title=' response = requests.get(url_cisco) for item in response.json(): lastPublished=item["lastPublished"] if format_today in lastPublished or format_yesterday in lastPublished: url_cisco = item["url"] title_cisco = item["title"] cve_cisco = item["cve"] summary_cisco = item["summary"] vul_date = lastPublished vul_string = f"脆弱性URL是:{url_cisco}\n脆弱性标题是:{title_cisco}\n脆弱性概要是:{summary_cisco}\n脆弱性CVE编号是:{cve_cisco}\n脆弱性更新时间是:{vul_date}\n" if cisco_list !=[]: cisco_result = '\n\n'.join(cisco_list) return(cisco_result) else: return("思科没有新脆弱性!")
###########纸上得来终觉浅,绝知此事要躬行###########