• crawler_exa4


    优化中...

    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author: Tdcqma
    
    '''
        获取漏洞目标站点:绿盟安全漏洞通告
    
    v1.0:
        由于网站结构存在变更的可能性,一旦爬虫爬取的页面发生变化则会影响正则表达式的匹配,导致爬虫失效。为了解决这个问题重新架构该爬虫,新的爬虫将分3个部分,即:
        【1】信息收集:一旦网站结构发生变化只需要更改此部分的正则表达式即可,收集的信息需要保存至一个嵌套列表中。
        【2】信息筛选:即使网站结构发生变化也不需要变更此部分。
        【3】信息发送:即使网站结构发生变化也不需要变更此部分。
    v1.1
        添加 "风险级别" 功能到报警信息中,由【CVE 通用漏洞与披露】库中获取对应漏洞的风险级别
    v1.2
        添加漏洞总数功能
    v1.3
        删除"风险级别"选项,因为http://cve.scap.org.cn/站点故障
        优化代码
    v1.4
        使用BeautifulSoup模块优化内容搜索
    v1.5
        优化模块2(信息筛选),对信息进行按系统分类显示
    v1.6
        优化v1.5部分,对代码部分进行函数化整理
    '''
    
    import urllib.request
    import ssl,re
    import smtplib,email
    import datetime
    from bs4 import BeautifulSoup
    
    # ---------------------------------------------
    # 【1】信息收集,正则表达匹配网站信息,包括date、title、url等,
    #      将所有信息保存至sec_all_list列表中
    # ---------------------------------------------
    
    f = open("secInfo-lvmeng.txt", 'w', encoding='utf-8')
    
    # 爬虫爬取当天的漏洞告警信息,也可指定如2017-10-09样式的日期格式用于开发过程中的测试
    #today = str(datetime.date.today())
    today = "2017-09-28"
    
    # 指定爬虫网站的首页链接
    sec_vul_domain = "http://www.nsfocus.net/"
    
    # 生成字典用于保存漏洞网站的跳转链接
    vul_dict = {}
    
    # 该变量保存漏洞跳转页面链接:http://www.nsfocus.net/index.php?act=sec_bug
    sec_vul_homepage = ""
    
    # 收集所有漏洞信息并保存在列表中
    sec_all_list = []
    
    # 将列表漏洞转换为字符串
    data_str = ""
    
    # 将需要监控的系统名称添加至该列表即可实现爬虫功能
    system_list = ["Apache","Cisco","Samba","Dnsmasq","Microsoft"]
    
    # 该变量保存所有指定系统的格式化后的漏洞信息,邮件发送也是基于该变量里保存的漏洞信息
    all_vul_msg = ""
    
    # 计算漏洞总数
    count = 0
    
    # 传入不同的page链接以获取相应response
    def get_response(vul_url):
        request = urllib.request.Request(vul_url)
        # 当尝试访问https开始当站点时,设置全局取消SSL证书验证
        ssl._create_default_https_context = ssl._create_unverified_context
        response = urllib.request.urlopen(request)
        data = response.read().decode('utf-8')
        return data
    
    data_homepage = get_response(sec_vul_domain)
    soup = BeautifulSoup(data_homepage, features="lxml")
    tag1 = soup.find_all(name='a')
    for item in tag1:
        if "安全漏洞" in item:
            # 通过获取标签属性,即使站点结构发生变化也能拿到漏洞页面的链接
            attrs = item.attrs
            vul_dict = attrs.copy()
    sec_vul_homepage = vul_dict.get('href')
    
    # 同一天的爆出的漏洞个数可能要占用好几个页面,需指定被扫描网站需要扫描的网页数范围,默认读取10页
    for i in range(10):
        sec_vul_pageNoUrl = sec_vul_homepage +"&type_id=&os=&keyword=&page=%s" % (i+1)
        data_sec_vul = get_response(sec_vul_pageNoUrl)
    
        if today in data_sec_vul:
    
            str_re = "<span>"+today+"</span>.*"
            res = re.findall(str_re,data_sec_vul)
    
            for item in res:
                data_str += item + '
    '
    
            sec_vul_soup = BeautifulSoup(data_str, features="lxml")
            tag_a = sec_vul_soup.find_all(name='a')
    
            for item in tag_a:
                # 生成列表用于收集单独的漏洞信息
                sec_sub_list = []
    
                # 收集漏洞标题: title
                sec_sub_title = item.string
                sec_sub_list.append(sec_sub_title)
    
                # 收集漏洞url: sec_sub_url
                item = str(item)
                sub_url = re.findall("vulndb/d+",item)
                sec_sub_url = sec_vul_domain + sub_url[0]
                sec_sub_list.append(sec_sub_url)
    
                # 收集漏洞受影响的版本: aff_ver
                data_sec_vul_cve = get_response(sec_sub_url)
                affected_version = re.findall("<blockquote>.*</blockquote>", data_sec_vul_cve, re.S)
                affected_version = str(affected_version[0][12:-13])
                affected_version = affected_version.replace("<br />", "")
                affected_version = affected_version.replace("&gt;",">")
                affected_version = affected_version.replace("&lt;","<")
                aff_ver = affected_version.replace("</blockquote><b>不受影响系统:</b><blockquote>","
    不受影响版本:
    ")
                sec_sub_list.append(aff_ver)
    
                if sec_sub_list not in sec_all_list:
                    sec_all_list.append(sec_sub_list)
    
    # ---------------------------------------------
    # 【2】信息筛选
    # ---------------------------------------------
    
    # 各系统漏洞在筛选后最终会保存至各自msg_***变量中,
    # >>>添加新监控系统时需相应添加以下记录<<<
    msg_cisco = ">>> CISCO安全通告
    "
    msg_apache = "
    >>> APACHE安全通告
    "
    
    # 调用sub_sec_info方法,将漏洞信息格式化输出
    def sub_sec_info():
        global count
        count += 1
        sec_info = "
    漏洞名称:" + line[0] 
                   + "
    漏洞链接:" + line[1] 
                   + "
    受影响的系统:
    " + line[2] + '
    '
        return sec_info
    
    # 调用get_sec_info函数,将目标系统或应用名称作为参数传入,即可获取相关爬虫告警信息
    def get_sec_info(vul):
        vul = vul.capitalize()
        global msg_cisco
        global msg_apache
    
        # >>>添加新监控系统时需相应添加以下elif记录<<<
        if vul in line[0]:
            if "Cisco" in vul:
                msg_cisco += sub_sec_info()
            elif "Apache" in vul:
                msg_apache += sub_sec_info()
    
    # 漏洞信息筛选入口函数
    for line in sec_all_list:
        for sys in system_list:
            get_sec_info(sys)
    
    # >>>添加新监控系统时需相应添加以下记录<<<
    all_vul_msg += msg_cisco
    all_vul_msg += msg_apache
    all_vul_msg += "
    漏洞总数:【"+str(count)+""
    
    # 为放置数据丢失,同时将筛选后的爬虫信息写入文本f中,f指向secInfo-lvmeng.txt文档。
    f.writelines(all_vul_msg)
    #print(msg)
    
    # ---------------------------------------------
    # 【3】信息发送
    # ---------------------------------------------
    
    # 配制收发邮件客户端
    chst = email.charset.Charset(input_charset = 'utf-8')
    header = ("From: %s
    To: %s
    Subject: %s
    
    " %
              ("from_mail@163.com",
               "to_mail@163.com",
               chst.header_encode("[爬虫安全通告-绿盟]")))
    
    #借用163smtp服务器发送邮件,将上面读到的报警信息(all_vul_msg)作为邮件正文发送。
    email_con = header.encode('utf-8') + all_vul_msg.encode('utf-8')
    smtp = smtplib.SMTP("smtp.163.com")
    smtp.login("from_mail@163.com","from_mail_pass")
    smtp.sendmail('from_mail@163.com','to_mail@163.com',email_con)
    print('mail send success!')
    smtp.quit()

    邮件截图:

  • 相关阅读:
    字符编码与解码详解
    【Java反射机制】用反射改进简单工厂模式设计
    数据结构
    根据 中序遍历 和 后序遍历构造树(Presentation)(C++)
    【动态规划】记忆搜索(C++)
    Linux环境下安装中山大学东校区iNode客户端
    webpack前端开发环境搭建
    CSS中line-height继承问题
    MySQL中MyISAM与InnoDB的主要区别对比
    JavaScript中易混淆的DOM属性及方法对比
  • 原文地址:https://www.cnblogs.com/tdcqma/p/7662988.html
Copyright © 2020-2023  润新知