阿里云漏洞敏捷管理自动化报告
一、需求
某天,有个客户提了个需求,需要我们每个月定期发送应急漏洞和系统漏洞的报表,并需要手动关联项目代码和供应商负责人等相关信息。
我们在操作过程中遇到以下几个问题:
1、客户的云安全中心是免费版本,无法点击下载按钮一键下载,只能通过api去调,生成自动报表
2、手动操作通过谷歌浏览器安装XPATH插件,提取字段列模式,生成Excel表格,并关联各个字段生成报表,手动操作耗时耗力,无法避免人操作失误
漏洞自动化流程图:
二、应用场景实践
1、了解阿里云OpenAPI
阿里云 OpenAPI 开发者门户是一款集 OpenAPI 智能搜索、OpenAPI 文档、OpenAPI 在线调试、SDK 获取、CodeSample、调用出错诊断、调用统计。您可以在 OpenAPI Explorer 中调用阿里云各云产品开放的 API,查看API请求和返回结果。此外,OpenAPI Explorer 会自动生成相应 API 的 SDK 调用示例,帮助您使用阿里云 API。
OpenAPI Explorer 登录地址:https://next.api.aliyun.com。
OpenAPI Explorer 提供以下功能
• API 检索
汇集阿里云多个产品的 API,可以在此集中检索,快速找到您所需要的 API。
• API 调用
无需编写代码,在调用页面中填写请求参数,便可调用 API。
• 查看 API 请求
根据您填写的请求参数自动生成 API 请求,并打印到网页上,让您直观的查看到真实发送的 API 请求。
• 结构化输出返回结果
根据 API 请求,返回真实的 API 调用结果,结构化输出。
• 生成 SDK 调用示例
根据输入的 API 请求参数,自动生成多种语言的 SDK 调用示例。
• 命令行调用
提供网页版命令行工具,模拟 Linux 操作体验使用命令行调用 API。
使用场景
OpenAPI Explorer 致力于帮助您更快地查找阿里云云产品 API 、更便捷地使用阿里云的 API 进行二次开发。您可以使用 OpenAPI Explorer 来检索阿里云开放了哪些 API、查看 API 定义,适用于 API 调试、故障排查等场景。
•API 调试
在基于阿里云 API 进行二次开发前,您可以预先验证 API 请求方式和查看 API 的返回结果。OpenAPI Explorer 提供了网页和命令行两种方式,让您直观的查看 API 的调用结果。而且,当调用出错时,OpenAPI Explorer 还会提示您如何解决。
•查看 SDK 示例
在您使用 SDK 进行开发时,往往需要一些代码示例来辅助您进行开发。在 OpenAPI Explorer 中输入 API 请求参数的同时,会帮您生成 Java、PHP、Python、Node.js 的示例代码,以引导您进行开发。
2、扫描漏洞
在了解了阿里云OpenAPI之后,我们尝试使用它完成第一个需求,使用python脚本自动开启控制台漏洞修复页面的一键扫描功能,这里以。
开启控制台漏洞修复页面的一键扫描功能API地址:
https://next.api.aliyun.com/api/Sas/2018-12-03/ModifyStartVulScan?params={}
第一步、OpenAPI 在线调试
打开上面的链接地址,找到“开启控制台漏洞修复页面的一键扫描功能”这个API,按照需求填写服务地址和参数(注意:带星号的参数必填),填完参数后点击“发起调用”按钮。可以看到右边画圈位置,“200 OK”则调用完成且成功,并在下方查看调用后的结果。如果调用失败,请根据错误提示,修改API请求。
可以看到云安全中心已经开始扫描应用漏洞了。
更多接口详细信息,请看API文档,地址:https://next.api.aliyun.com/document/Sas/2018-12-03/ModifyStartVulScan
第二步、使用 SDK 进行二次开发
首先,按照下图所示,获取SDK安装命令,在本地执行安装SDK。
Python
pip install alibabacloud_sas20181203==1.1.29
安装完SDK依赖后,按照下图所示,根据需求填写服务地址和参数。点击“SDK示例”按钮,我这里是使用python语言进行的二次开发,所以这边选择“Python”按钮,复制下面的示例代码,按照下面的步骤进行修改后方可使用。另外,如果在参数配置中填写了参数,则会自动将该参数填写到SDK示例代码中,对我们新手来说非常友好。
那参数该怎么填呢?如下图所示,将鼠标移至参数旁的问号图标上,即可看到可以设置哪些取值。
填写cve,则只会扫描Linux软件漏洞;填写sys,则只会扫描Windows系统漏洞;同理,......。注意看下面的说明,如果该职位空,会检测所有漏洞类型。所以在填写参数的时候一定要看仔细,尤其是一些危险的操作,确保没问题后再执行。
将复制过来的代码进行修改,删除了其中异步的main_async函数,这里我们不需要用到异步。这里主要是需要填写AccessKey,我发现需要填写两处,索性就创建两个变量,那两处需要填写AccessKey的地址,直接用变量代替,如下代码框中所示。其余的可以按照自己的需求进行二次开发,我这边没有其他需要变更的需求了,所以这里也就不做另外的改动了。
若是不清楚AccessKey是什么,该怎么创建,请参见创建AccessKey链接地址为:https://help.aliyun.com/document_detail/116401.htm?spm=a2c4g.11186623.0.0.b22b48f5z7iKkL#task-2245479
并且需要给到该用户相应的权限,否则也是无权限调用该API,会导致执行失败。
Python
# -*- coding: utf-8 -*-
import sys
from typing import List
from alibabacloud_sas20181203.client import Client as Sas20181203Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_sas20181203 import models as sas_20181203_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
ak="" #请在此处填写您的 AccessKey ID
sk="" #请在此处填写您的 AccessKey Secret
class Sample:
def __init__(self):
pass
@staticmethod
def create_client(
access_key_id: str,
access_key_secret: str,
) -> Sas20181203Client:
config = open_api_models.Config(
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
access_key_id=ak,
access_key_secret=sk
)
config.endpoint = f'tds.aliyuncs.com'
return Sas20181203Client(config)
@staticmethod
def main(
args: List[str],
) -> None:
#我对这一行代码进行了修改,采用变量的方式,无需重复填写AKSK
client = Sample.create_client(ak,sk)
modify_start_vul_scan_request = sas_20181203_models.ModifyStartVulScanRequest(
types='emg' #这里以应急漏洞为例,所以只扫描应急漏洞
)
runtime = util_models.RuntimeOptions()
try:
client.modify_start_vul_scan_with_options(modify_start_vul_scan_request, runtime)
except Exception as error:
UtilClient.assert_as_string(error.message)
if __name__ == '__main__':
Sample.main(sys.argv[1:])
执行上面的脚本后,进入云安全中心检查,查看应急漏洞是否正在扫描,如下图所示即为正在扫描应急漏洞,否则请检查代码是否正确。
3、导出漏洞列表
找到“导出漏洞列表”的API,填写参数配置,这里我填写了如下图所示的参数,导出应急漏洞,漏洞修复优先级为高,且未修复的漏洞信息。
填写完相关参数后,点击“发起调用按钮”。可以看到调用结果并不是我们想象中的直接下载文件
在该API文档中有明确说明:“本接口与DescribeVulExportInfo接口配合使用。使用本接口建立漏洞导出任务之后,可调用DescribeVulExportInfo接口录入漏洞导出任务的ID,查看漏洞导出任务的进度。”所以,我们需要先取出漏洞导出任务的ID,再配合DescribeVulExportInfo接口才能下载导出的列表。
接下来就是对这个接口进行二次开发,取出我们所需要的“漏洞导出任务的ID”。如下图所示,在填写完所需参数后,复制右边的python SDK示例代码。
按照上面讲过的方法,采用变量的方式,填写完AccessKey后运行下面代码。
Python
# -*- coding: utf-8 -*-
import sys
from typing import List
from alibabacloud_sas20181203.client import Client as Sas20181203Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_sas20181203 import models as sas_20181203_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
ak="" #请在此处填写您的 AccessKey ID
sk="" #请在此处填写您的 AccessKey Secret
class Sample:
def __init__(self):
pass
@staticmethod
def create_client(
access_key_id: str,
access_key_secret: str,
) -> Sas20181203Client:
config = open_api_models.Config(
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
access_key_id=ak,
access_key_secret=sk
)
config.endpoint = f'tds.aliyuncs.com'
return Sas20181203Client(config)
@staticmethod
def main(
args: List[str],
) -> None:
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
client = Sample.create_client(ak, sk)
export_vul_request = sas_20181203_models.ExportVulRequest(
type='emg',
lang='zh',
necessity='asap',
dealed='n'
)
runtime = util_models.RuntimeOptions()
try:
# 复制代码运行请自行打印 API 的返回值
client.export_vul_with_options(export_vul_request, runtime) #提示:下面我们将对这一部分进行修改
except Exception as error:
# 如有需要,请打印 error
UtilClient.assert_as_string(error.message)
if __name__ == '__main__':
Sample.main(sys.argv[1:])
运行后,发现并没有输出结果。按照提示对代码进行修改和打印
Python
print(client.export_vul_with_options(export_vul_request, runtime))
输出的结果如下图所示,这是使用“python代码美化工具”美化后的结果,便于我们查看。发现其中的Id正是我们所需要的“漏洞导出任务的ID”。下面将讲述如何取出我们所需要的Id。
使用type函数,查看这个变量的类型,第一行为修改后的代码,井号后面的内容即为打印后的结果,可以看到这个变量是一个class类。
type() 函数属于Python内置函数,通常用来查看某个变量的具体类型
Python
print(type(client.export_vul_with_options(export_vul_request, runtime)))
#<class 'alibabacloud_sas20181203.models.ExportVulResponse'>
使用__dict__ 打印这个类中所有的属性,从打印结果中大致知道headers里是一些头信息,status_code是响应状态码,body是响应内容,而我们需要的Id应该在响应内容中。
在Python类的内部,无论是类属性还是实例属性,都是以字典的形式进行存储的,其中属性名作为键,而值作为该键对应的值。 为了方便用户查看类中包含哪些属性,Python 类提供了 __dict__ 属性。需要注意的一点是,该属性可以用类名或者类的实例对象来调用,用类名直接调用 __dict__,会输出该由类中所有类属性组成的字典;而使用类的实例对象调用 __dict__,会输出由类中所有实例属性组成的字典。
Python
print(client.export_vul_with_options(export_vul_request, runtime).__dict__)
使用“类名.属性”的方式获取属性的值,如下所示获取body属性的值,并使用type函数查看该值是属于什么类型。上面这行是修改后的代码,井号后面的内容为输出的结果,我们发现这个值也是一个类。
Python
print(type(client.export_vul_with_options(export_vul_request, runtime).body))
#<class 'alibabacloud_sas20181203.models.ExportVulResponseBody'>
同理,调用 __dict__查看这个类中的所有属性,发现了id这个属性,正是我所需要的“漏洞导出任务的ID”。
Python
print(client.export_vul_with_options(export_vul_request, runtime).body.__dict__)
#{'file_name': 'emg_20220831', 'id': 119828, 'request_id': '79B83B4B-1CE6-5987-9BDF-C3AB995E94D4'}
同理,使用“类名.属性”的方式获取属性的值。可以看到正是我们所需要的“漏洞导出任务的ID”。
Python
print(client.export_vul_with_options(export_vul_request, runtime).body.id)
#119828
最终调整后的代码如下所示:
Python
# -*- coding: utf-8 -*-
import sys
from typing import List
from alibabacloud_sas20181203.client import Client as Sas20181203Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_sas20181203 import models as sas_20181203_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
ak="" #请在此处填写您的 AccessKey ID
sk="" #请在此处填写您的 AccessKey Secret
class Sample:
def __init__(self):
pass
@staticmethod
def create_client(
access_key_id: str,
access_key_secret: str,
) -> Sas20181203Client:
config = open_api_models.Config(
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
access_key_id=ak,
access_key_secret=sk
)
config.endpoint = f'tds.aliyuncs.com'
return Sas20181203Client(config)
@staticmethod
def main(
args: List[str],
) -> None:
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
client = Sample.create_client(ak, sk)
export_vul_request = sas_20181203_models.ExportVulRequest(
type='emg',
lang='zh',
necessity='asap',
dealed='n'
)
runtime = util_models.RuntimeOptions()
try:
# 我对这行代码进行了调整,获取“漏洞导出任务的ID”
print(client.export_vul_with_options(export_vul_request, runtime).body.id)
except Exception as error:
UtilClient.assert_as_string(error.message)
if __name__ == '__main__':
Sample.main(sys.argv[1:])
4、查看漏洞导出任务的进度
获取到“漏洞导出任务的ID”之后,根据上面的API文档提示,找到“导出漏洞列表”的API,在参数配置中将获取到的“漏洞导出任务的ID”填入,并复制右侧代码进行二次开发。
查看该API文档,发现我们需要获取其中的“导出后Excel的下载链接”,才能下载导出的列表。
按照我上面讲述的方法,对代码进行修改,这里就不再重复了,修改后的代码如下所示:
Python
# -*- coding: utf-8 -*-
import sys
from typing import List
from alibabacloud_sas20181203.client import Client as Sas20181203Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_sas20181203 import models as sas_20181203_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
ak="" #请在此处填写您的 AccessKey ID
sk="" #请在此处填写您的 AccessKey Secret
class Sample:
def __init__(self):
pass
@staticmethod
def create_client(
access_key_id: str,
access_key_secret: str,
) -> Sas20181203Client:
config = open_api_models.Config(
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
access_key_id=ak,
access_key_secret=sk
)
config.endpoint = f'tds.aliyuncs.com'
return Sas20181203Client(config)
@staticmethod
def main(
args: List[str],
) -> None:
#我对这两行代码进行了修改,采用变量的方式,无需重复填写AKSK
client = Sample.create_client(ak, sk)
describe_vul_export_info_request = sas_20181203_models.DescribeVulExportInfoRequest(
export_id=119828 #此处填写第三步获取到的“漏洞导出任务的ID”
)
runtime = util_models.RuntimeOptions()
try:
# 我对这行代码进行了调整,获取“导出后Excel的下载链接”
print(client.describe_vul_export_info_with_options(describe_vul_export_info_request, runtime).body.link)
except Exception as error:
UtilClient.assert_as_string(error.message)
if __name__ == '__main__':
Sample.main(sys.argv[1:])
运行代码,即可得到导出后Excel的下载链接
5、下载并解压
安装wget包,使用wget进行下载。
Python
pip install wget
具体代码如下:
Python
import time,wget,ssl #导入所需要的包
ssl._create_default_https_context = ssl._create_unverified_context #关闭ssl认证
url="https://vul-export.oss-cn-shanghai.aliyuncs.com/export/emg_20220826_xxx.zip?Expires=xxx" #填写上面获取的“导出后Excel的下载链接”
now_time=time.strftime('%Y%m%d',time.localtime(time.time())) #定义当前时间的变量,获取当前的时间
zip_name="emg_{}.zip".format(now_time) #定义zip包名变量,以当前时间命名的zip包名
wget.download(url,out=zip_name) #使用wget下载,下载的zip包与当前代码在同级目录
执行上面的代码,在代码的同级目录中查看,是否新增了以当前时间命名的zip包,这个zip包就是我们所需的漏洞列表。
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
因为访问的网站是https://,需要SSL认证,而直接用urllib会导致本地验证失败(具体原因未查明),所以使用ssl._create_unverified_context关闭认证,否则会报下面这个错:
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)>
安装解压所需模块
Python
pip install zipfile36
解压zip包的代码如下
Python
import zipfile #导入所需模块
with zipfile.ZipFile("emg_20220826.zip") as zf: #解压zip包
zf.extractall()
执行代码,如下图所示"emg_20220826.xlsx"即为解压后的漏洞列表。
6、xlsx转成csv格式
excel本身的.xlsx格式导入数据库时可能会报错,为了避免不必要的格式错误,直接使用.csv格式,所以我们需要将xlsx转成csv格式。
安装所需模块
Python
pip install pandas
xlsx转成csv格式代码如下所示:
Python
import pandas as pd #导入所需模块
pd.read_excel("emg_20220826.xlsx", index_col=0).to_csv("emg_20220826.csv", encoding='utf-8') #xlsx转成csv格式
执行代码,如下图所示"emg_20220826.csv"即为转换后的csv漏洞列表。
在执行上面代码的过程中,发现输出了如下WARN日志:
UserWarning: Workbook contains no default style, apply openpyxl's default
warn("Workbook contains no default style, apply openpyxl's default")
中文翻译:
用户警告:工作簿不包含默认样式,请应用openpyxl的默认样式
警告(“工作簿不包含默认样式,应用openpyxl的默认样式”)
故障分析:
这个excel文件没有设置默认的样式。一般这种没有默认样式的excel文档是由java程序生成的,不是像windows系统日常使用中通过右键点击创建的excel文档。
解决方法:
第一种方法,导入warnings模块,忽略警告级别的提示。(这里我用的是这一种方法)
import warnings
warnings.simplefilter("ignore")
第二种方法,用excel程序,打开保存一下这个文档,使该文档程序属性变成Microsoft EXCEL,同时应该也保存了默认的excel样式
添加忽略警告级别提示后的代码如下所示:
Python
import pandas as pd
import warnings
warnings.simplefilter("ignore")
pd.read_excel("emg_20220826.xlsx", index_col=0).to_csv("emg_20220826.csv", encoding='utf-8')
7、关联供应商信息
这里我是使用数据库进行连表查询的方式,将供应商信息和漏洞列表相关联,并且将关联后的表导出成EXCEL表格,下面描述的是具体的操作:
在数据库中,新建如下两张表,webbugsec表即等下需要导入漏洞列表做准备,code表为项目及供应商信息的表格,可按照需求自行修改,但是需要存在两张表可以相互关联的字段,比如说:影响资产ID、影响资产备注名称、影响资产IP(公网)、影响资产IP(私网)等等。
Python
CREATE TABLE `webbugsec` (
`id` int(25) NOT NULL COMMENT '漏洞ID',
`vulnerability` varchar(100) NOT NULL COMMENT '漏洞名称',
`urgency_level` varchar(25) NOT NULL COMMENT '修复紧急度',
`affected_assets_id` varchar(25) DEFAULT NULL COMMENT '影响资产ID',
`affected_assets_ip_internet` varchar(50) DEFAULT NULL COMMENT '影响资产IP(公网)',
`affected_assets_ip_intranet` varchar(50) DEFAULT NULL COMMENT '影响资产IP(私网)',
`affected_assets_name` varchar(100) DEFAULT NULL COMMENT '影响资产备注名称',
`first_detect_time` varchar(50) NOT NULL COMMENT '首次发现时间',
`last_detect_time` varchar(50) NOT NULL COMMENT '最近一次发现时间',
`handle_time` varchar(50) DEFAULT NULL COMMENT '处理时间',
`note` varchar(1500) NOT NULL COMMENT '漏洞说明',
`status` varchar(25) NOT NULL COMMENT '漏洞状态',
`fix_command` varchar(100) DEFAULT NULL COMMENT '修复命令',
`cve_id` varchar(50) DEFAULT NULL COMMENT 'CVE编号',
`tags` varchar(50) DEFAULT NULL COMMENT '标签',
`suggestion` varchar(1500) NOT NULL COMMENT '修复建议'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
CREATE TABLE `code` (
`code` varchar(25) NOT NULL COMMENT 'code',
`affected_assets_name` varchar(50) NOT NULL COMMENT '影响资产备注名称',
`affected_assets_id` varchar(25) NOT NULL COMMENT '影响资产ID',
`affected_assets_ip_internet` varchar(50) DEFAULT NULL COMMENT '影响资产IP(公网)',
`affected_assets_ip_intranet` varchar(50) NOT NULL COMMENT '影响资产IP(私网)',
`project_description` varchar(100) DEFAULT NULL COMMENT '项目描述',
`bsm` varchar(100) NOT NULL COMMENT 'BSM'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
刚下载的漏洞列表第一行为中文列标题,如果直接导入,会出现如下报错:
我们需要对第一行列标题进行修改,改成与webbugsec表相对应的字段,具体代码如下所示:
Python
with open("emg_20220826.csv", 'r', encoding='utf8') as f:
msg = f.read()
msg = msg.replace(
"漏洞ID,漏洞名称,修复紧急度,影响资产ID ,影响资产IP(公网),影响资产IP(私网),影响资产备注名称,首次发现时间,最近一次发现时间,处理时间,漏洞说明,漏洞状态,修复命令,CVE编号,标签,修复建议",
'id,vulnerability,urgency_level,affected_assets_id,affected_assets_ip_internet,affected_assets_ip_intranet,affected_assets_name,first_detect_time,last_detect_time,handle_time,note,status,fix_command,cve_id,tags,suggestion')
with open("emg_20220826.csv", 'w', encoding='utf8') as f:
f.write(msg)
运行代码后,可以看到第一行列标题已进行修改,如下图所示:
剩下的就是将csv中的数据导入到webbugsec表中,并和code表进行连表查询,将各个漏洞信息与供应商信息相结合,并导出成EXCEL表格,代码如下所示:
Python
#导入所需模块
import pandas as pd #as表示给这个模块取别名,调用这个模块的时候直接用别名就可以了
from urllib import parse #表示使用ullib模块中的parse方法
from sqlalchemy import create_engine
#请填写数据库连接信息
user = "root"
password = "xxx"
host = "127.0.0.1"
db = "db_name"
pwd = parse.quote_plus(password) #是将一些特殊的字符串转换为固定的一些符号字母数字组合,若是密码中含有特殊字符,在连接数据库的时候也不会报错。
engine = create_engine(f"mysql+pymysql://{user}:{pwd}@{host}:3306/{db}?charset=utf8") #创建一个引擎对象,初始化数据库连接
connection = engine.connect() #创建一个连接对象
#清空webbugsec表中的所有数据
with engine.begin() as conn:
conn.execute("truncate table webbugsec")
#检查webbugsec表是否清空
print(pd.read_sql(sql="select * from webbugsec;", con=engine))
#读取xlsx文件
df=pd.read_csv("emg_20220826.csv")
#导入到mysql数据库中的webbugsec表中,如果存在则替换
df.to_sql(name='webbugsec', con=engine, index=False, if_exists='append')
#连表查询我们需要的数据,可按照自己的需求进行调整
db = pd.read_sql(sql="select w.affected_assets_name as '影响资产备注名称',c.code as 'CODE',c.project_description as '项目描述',c.bsm as 'BSM',w.affected_assets_id as '影响资产ID',w.affected_assets_ip_internet as '影响资产IP(公网)',w.affected_assets_ip_intranet as '影响资产IP(私网)',w.vulnerability as '漏洞名称', w.note as '漏洞说明',w.suggestion as '修复建议' from webbugsec w,code c where w.affected_assets_id=c.affected_assets_id ORDER BY c.code ASC;",con=engine)
#将查找到的内容导出到应急漏洞_20220826.xlsx表中
excel_o_file_name="./应急漏洞_20220826.xlsx"
excel_o_file = pd.ExcelWriter(excel_o_file_name)
db.to_excel(excel_o_file, index=False, encoding='utf-8', sheet_name='Sheet1')
excel_o_file.save()
#关闭数据库连接
connection.close()
数据库连接是有限制的,如果连接不关闭,而且使用的人比较多,那么系统很快就down掉了,所以需要在代码末尾关闭数据库连接。
执行上面的代码后,导出的EXCEL表格内容,如下图所示:
8、通知
邮件通知
如下为发送邮件的代码:
Python
import smtplib
from urllib import parse
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name):
message = MIMEMultipart()
message['From'] = MAIL_USERNAME # 发件人
message['To'] = ";".join(accept_list) # 收件人,将列表转换为字符串
message["Cc"] = ";".join(Cc_list) # 抄送人,将列表转换为字符串
message['Subject'] = SUBJECT # 邮件主题
message.attach(MIMEText(text, 'plain', 'utf-8')) # 格式化邮件内容,编码为utf-8
att1 = MIMEText(open(file_name, 'rb').read(), 'base64', 'utf-8') # 添加附件
att1["Content-Type"] = 'application/octet-stream' # 设置类型
#附件名称为中文时的写法
att1.add_header('Content-Disposition', 'attachment', filename = "应急漏洞_20220831.xlsx")
#附件名称非中文时的写法
#att1["Content-Disposition"] = 'attachment; filename="{0}"'.format(parse.quote_plus("应急漏洞_20220831.xlsx")) # 设置邮件用现实的名称
message.attach(att1)
try:
#使用25端口,不启用ssl
#mailServer = smtplib.SMTP(MAIL_SERVER, 25)
#使用465端口,启用ssl
mailServer = smtplib.SMTP_SSL(MAIL_SERVER, 465)
# 登录邮箱
mailServer.login(MAIL_USERNAME, MAIL_PASSWORD) # 需要的是,邮箱的地址和授权密码
# 发送文件
mailServer.sendmail(MAIL_USERNAME, accept_list + Cc_list, message.as_string())
mailServer.close() # 关闭连接
return True
except Exception as e:
print(e)
return False
def main():
MAIL_SERVER = '' # smtp服务器
MAIL_USERNAME = '' # 发件人
MAIL_PASSWORD = '' # 发送者授权码或密码
accept_list = ['', ] # 收件人,多个收件人用列表的方式填写
Cc_list = ['',] # 抄送人,多个抄送人用列表的方式填写
SUBJECT = "云安全中漏洞管理" # 主题
text = "云安全中心漏洞管理:\n应急漏洞:emg_20220729.xlsx文件大小[33kb]" # 内容
file_name = "./应急漏洞_20220831.xlsx" # 附件路径
print(send_mail(MAIL_SERVER, MAIL_USERNAME, MAIL_PASSWORD, accept_list, Cc_list, SUBJECT, text, file_name))
if __name__ == '__main__':
main()
收到的邮件内容如下图所示:
钉钉通知
安装钉钉通知模块
Python
pip install DingtalkChatbot
我在机器人的关键字中定义了「通知」关键字,我们来看如下代码来实现发送消息:
Python
from dingtalkchatbot.chatbot import DingtalkChatbot
# 初始化机器人
xiaoding = DingtalkChatbot('这里填写WebHook地址')
# Text消息并@指定用户
xiaoding.send_text(msg="这里填写通知内容", at_mobiles=['这里填写要@的用户与钉钉绑定的手机号',])
钉钉群里将会收到这样一条通知:
另外我加上了查看文件大小及使用markdown格式的钉钉通知,代码如下所示:
Python
from dingtalkchatbot.chatbot import DingtalkChatbot
import os
# 初始化机器人
xiaoding = DingtalkChatbot('这里填写WebHook地址')
# 查看导出的表格大小
filesize = int(os.path.getsize("./应急漏洞_20220831.xlsx")/1024)
# 使用markdown格式发送钉钉通知,并@指定人员
xiaoding.send_markdown(title="云安全中心漏洞管理",text='### 云安全中心漏洞管理\n\n**应急漏洞:**emg_20220729.xlsx文件大小[{}kb]\n\n'.format(filesize), at_mobiles=['这里填写要@的用户与钉钉绑定的手机号', ])
最终钉钉通知的效果:
9、定时任务
生产环境是在每个月第三周的周四打补丁,非生产环境是第二周的周四。所以需要在这之前,第二周的周三将漏洞列表给导出来。下面是我用crontab做的定时任务,
Python
[root@iZuf6d2ri21ufpdxZ ~]# crontab -l
#阿里云云安全中心漏洞任务
10 8 8 * * /usr/local/bin/python3 /usr/local/aliyun/ali-secemg.py
10、总结
a. 脚本具有可复用行,可以在其他项目或者供应商中使用。
b. 由于脚本是定期自动执行的,所以不存在遗忘和执行过程中的疏忽。
c. 重要的是更好地利用资源,将繁琐的任务自动化,可以提高准确性和运维人员的积极性,将运维人员解脱出来,投入更多精力投入到重要的事情上。
三、各类安全工具推荐
1、定期基线扫描
推荐使用TiOPS或者开源的软件或者编写的脚步shell、powershell
2、web渗透测试
推荐使用Burpsuite、Nessus、Appscan、AWVS、QualysGuard 、Netsparker等
3、系统补丁更新
各大厂商官方源或自建的源 Windows搭建WSUS Linux yum仓库源
文章转载自公众号:新钛云服
/usr/local/aliyun/ali-secemg.py 辛苦大佬这个脚本提供一下