精通机器学习渗透测试(二)
原文:
annas-archive.org/md5/74E92091FA78BD2C9635BCA05C8FE700译者:飞龙
第六章:异常检测系统中的机器学习
对于任何企业来说,网络上的未经授权活动可能是一场噩梦。保护客户数据是最重要的问题,也是每个企业所有者的责任。部署入侵检测系统是现代组织可以采取的明智决定,以防御恶意入侵。不幸的是,攻击者和黑客总是在想出新的技术来绕过保护,以获取对网络的未经授权访问。这就是为什么机器学习技术是保护网络免受甚至复杂和攻击的良好解决方案。
本章将是发现网络异常并学习如何从头开始构建入侵检测系统的一站式指南,使用公开可用的数据集和尖端的开源 Python 数据科学库。
在本章中,我们将涵盖以下内容:
-
异常检测技术概述
-
网络攻击
-
检测网络异常
-
基于主机的入侵检测系统(HIDS)
-
基于网络的入侵检测系统(NIDS)
技术要求
本章需要以下要求:
-
本章需要对网络有一定的了解。
-
我们将使用在之前章节中看到的相同的 Python 库,还有一个名为Yellowbrick的新库。(你将在本章中找到安装说明。)
-
您可以在 GitHub 存储库中找到本章中使用的代码文件
github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter06。
异常检测技术概述
我们现在将讨论网络异常(这是我们主要关注的内容)及其检测方法。根据定义,异常是指数据中的异常模式,即超出正常范围的意外模式。异常这个术语在数据挖掘中被广泛使用,有时被称为异常值。异常检测技术通常用于欺诈检测和发现恶意活动。在网络中,异常可能由于许多原因而发生,但对我们来说,重要的是恶意活动的检测。通常,我们看到三种类型的异常:
-
点异常:与其余数据相比,异常的个别数据实例。
-
上下文异常:仅在特定上下文(时间段、地区等)中发生的异常行为。
-
集体异常:与其余数据相比,一系列异常活动。
这些异常可以使用许多技术来检测,这些技术基于可用的数据。
静态规则技术
如果我们有训练数据,那么我们需要检查数据是否平衡。如果没有训练数据,决策将基于异常类型进行;要检测点异常,建议使用百分位数和直方图。要检测集体异常,决策将基于异常的方差;要检测单变量异常,可以使用马尔可夫链,或者可以构建模型并查看残差。在多变量情况下,我们可以使用聚类和马尔可夫模型(如果异常是有序的),或者 k-最近邻(如果异常是无序的)。
不同的技术在下图中表示:
网络攻击分类
在网络异常方面,我们的工作是保护组织的网络免受入侵者的侵害。网络入侵是威胁网络安全的恶意活动。信息安全专业人员已经提出了许多分类来对网络攻击进行更好的研究。例如,他们已经将网络攻击分类为以下几类:
-
感染(恶意软件)
-
爆炸(缓冲区溢出)
-
探测(嗅探)
-
作弊(欺骗)
-
遍历(暴力破解)
-
并发(DDoS)
攻击也可以分为被动和主动攻击。主动攻击是指攻击者对网络产生直接影响。国防高级研究计划局(DARPA)在其入侵检测评估计划中将主动攻击分为四大类。这四类如下:
-
拒绝服务(DoS):DoS 攻击是试图中断授权用户对网络的访问的尝试。换句话说,它们阻止用户访问在线服务,如电子邮件。
-
用户到根(U2R)攻击:U2R 攻击很难检测;它们试图获得高(超级用户)权限。这是通过以普通用户的身份访问系统,并尝试后来利用系统的弱点来提升权限来实现的。
-
远程到本地(R2L):R2L 攻击是尝试与远程机器交互以获取访问权限。使用的一种技术是猜测密码。
-
探测:探测是获取有关网络中主机的信息的尝试,包括有效的 IP 地址、运行的服务和开放的端口。通常是通过扫描完成的。如您所知,收集的信息将稍后用于识别漏洞以利用它们。
网络异常的检测
网络入侵检测系统(IDSs)并不是一个新的想法。自最早的网络攻击以来就提出了 IDS。IDS 可以根据其部署分为两大类:HIDS 和 NIDS。以下图表说明了 IDS 架构的高级概述:
HIDS
HIDS 能够收集和监视计算机系统(特别是它们的内部),以便为安全分析人员提供对关键系统(如工作站、服务器和移动设备)发生的情况的深入可见性。HIDS 的主要目标是检测入侵。
NIDS
NIDS 负责检测网络数据中的入侵。基本上,检测是基于顺序数据中的特定模式进行的。换句话说,NIDS 读取所有传入的数据包,并尝试在其中找到异常。
基于异常的 IDS
在谈到 IDS 时,我们通常谈论两类:基于主机和基于网络的。但也出现了一种新的 IDS 类别。新类别是基于异常的。这些系统通过使用机器学习技术来识别数据中的入侵和异常。在以前的章节中,特别是在第一章,渗透测试中的机器学习简介中,我们看到了不同的机器学习模型:受监督的、无监督的、半监督的和强化学习。基于异常的 IDS 也根据用于检测网络入侵的机器学习模型被分类为受监督和无监督系统。信息安全社区经过多年的研究,已成功提供了 IDS 中使用的不同方法的分类。其中一项提议,名为浅层和深层网络入侵检测系统:分类和调查,由 Elike Hodo、Xavier J. A. Bellekens、Andrew Hamilton、Christos Tachtatzis 和 Robert C. Atkinson 提出,对可靠入侵检测的许多机器学习技术进行了详细概述。以下图表中呈现了一些技术:
正如您所看到的,我们在前几章讨论了许多建议的技术。通常,在受监督的异常检测中,输入数据和异常类是已知的。换句话说,所有数据都是标记的;即使收集标记的数据也是一项繁重和耗时的任务。捕获的数据将在发送到检测引擎之前进行处理。无监督的异常检测系统可能是新颖的解决方案,即使数据没有标记也可以工作。
聚类是无监督系统中最常用的技术之一。这两种不同的系统可以合并成一个混合入侵检测系统。下面显示了一个总体混合异常入侵检测系统:
如果您想要构建一个成功和可靠的基于异常的网络入侵检测系统,您需要考虑许多重要因素。其中之一是接近度测量;根据定义,接近度意味着对对象的相似性或不相似性进行测量。因此,正如之前讨论的那样,这些系统试图将数据分类或分组,因此相应地测量对象之间的接近度。相似性度量的取值范围在0和1之间,其中1是最大的相似性值。欧几里得距离和曼哈顿距离是一些常见的接近度测量。合适的测量方法的选择取决于数据的类型(数值或分类)。异常不是任意检测的,而是基于评分系统。子样本由称为异常分数的入侵分数标记。这种评分系统对信息安全分析人员非常有益;基于有序和排名的异常列表,他们可以选择根据严重性来工作的阈值。以下是异常网络入侵检测系统使用的一些常见异常评分技术:
-
基于距离的异常分数估计:
-
演变数据集中基于链接的离群值和异常检测:数据集包含连续和分类属性。它使用相似性度量来衡量链接强度和两个点之间的关联程度。
-
减少内存负载:这将异常定义为具有子集属性的数据点,这些属性具有不寻常的值。
-
基于密度的异常分数估计:
-
混合属性数据集的离群检测:通过计算值的不规则性和不同类型属性之间的关系来检测异常。
构建您自己的 IDS
到目前为止,您已经了解了不同的网络异常检测技术。现在我们将使用 Python 从头开始构建我们自己的网络 IDS。加利福尼亚大学举办了一场名为《第三届国际知识发现和数据挖掘工具竞赛》的比赛,他们提供了一个名为KDD Cup 1999 Data或KDD 1990的数据集。您可以在kdd.ics.uci.edu/databases/kddcup99/kddcup99.html找到它。
比赛的主要目的是构建一个能够区分恶意(攻击)和良好(正常)连接的系统。许多现代提案和机器学习解决方案都使用了数据集。但是正如你所看到的,数据集已经过时;这些模型无法检测到现代网络攻击,除了其他问题,如数据冗余。一项名为《KDD CUP 99 数据集的详细分析》的研究,由 Mahbod Tavallaee、Ebrahim Bagheri、Wei Lu 和 Ali A. Ghorbani 完成,突出了 KDD99 数据集中的许多问题。出现了一个新的数据集来解决这些问题,名为 NSL-KDD(www.unb.ca/cic/datasets/nsl.html)。即使这也没有解决所有问题,但是进行了许多改进。这些改进减少了大约 75%的数据。
以下是一些额外的公开可用数据集,可以帮助您构建自己的入侵检测系统:
-
科堡入侵检测数据集(CIDDS):
www.hs-coburg.de/index.php?id=927 -
UGR'16,用于周期站点网络 IDS 评估的新数据集:
nesg.ugr.es/nesg-ugr16/index.php#CAL -
入侵检测评估数据集(CICIDS2017):
www.unb.ca/cic/datasets/ids-2017.html
对于我们的模型,我们将使用NSL_KDD作为训练和测试的数据集。要获得它,只需从 GitHub 克隆它,或者直接使用它,因为我们在书的 GitHub 存储库中提供了本书中讨论的所有数据集。你可以在Chapter 06文件夹中找到它:
# git clone https://github.com/defcom17/NSL_KDD
数据集包含不同的文件:
-
KDDTrain+.arff:带有二进制标签的完整 NSL-KDD 训练集,以 ARFF 格式。 -
KDDTrain+.txt:包含攻击类型标签和 CSV 格式的完整 NSL-KDD 训练集。 -
KDDTrain+_20Percent.ARFF:KDDTrain+.arff文件的 20%子集。 -
KDDTrain+_20Percent.TXT:KDDTrain+.txt文件的 20%子集。 -
KDDTest+.ARFF:带有二进制标签的完整 NSL-KDD 测试集,以 ARFF 格式。 -
KDDTest+.TXT:包含攻击类型标签和 CSV 格式的难度级别的完整 NSL-KDD 测试集。 -
KDDTest-21.ARFF:KDDTest+.arff文件的子集,不包括记录,难度级别为 21/21。 -
KDDTest-21.TXT:KDDTest+.txt文件的子集,不包括记录,难度级别为 21/21。
如果你打开Field Names.csv,你会看到所有的 40 个字段:
导入这个数据集,我们将使用pandas:
>>> import pandas as pd
>>> Data = pd.read_csv("KDDTrain+.csv", header=None)
如果我们检查Data.columns中的列,我们会看到列或字段被表示为数字:
为了使我们的特征分析更容易,让我们为更好的特征表示给一个字段名称分配一个数字。为了做到这一点,我们将创建一个名为Columns的数组,其中填充了字段名称,并用它加载数据集:
Columns = ["duration","protocol_type","service","flag","src_bytes",
"dst_bytes","land","wrong_fragment","urgent","hot","num_failed_logins",
"logged_in","num_compromised","root_shell","su_attempted","num_root",
"num_file_creations","num_shells","num_access_files","num_outbound_cmds",
"is_host_login","is_guest_login","count","srv_count","serror_rate",
"srv_serror_rate","rerror_rate","srv_rerror_rate","same_srv_rate",
"diff_srv_rate","srv_diff_host_rate","dst_host_count","dst_host_srv_count",
"dst_host_same_srv_rate","dst_host_diff_srv_rate","dst_host_same_src_port_rate",
"dst_host_srv_diff_host_rate","dst_host_serror_rate","dst_host_srv_serror_rate",
"dst_host_rerror_rate","dst_host_srv_rerror_rate","label","difficulty"]
加载数据:
Data = pd.read_csv("KDDTrain+.csv", header=None, names = Columns)
Data.columns
这些是特征名称:
为了更好地理解数据集,我们可以使用pandas.DataFrame.describe:
Data.describe()
在训练模型之前,需要进行一些额外的处理。sklearn.preprocessing.LabelEncoder将标签编码为介于0和n_classes-1之间的值,并fit_transform(y)。适应标签编码器并返回编码标签。在我们的情况下,我们正在将非数字标签转换为数字标签。此外,我们需要预处理四个标签:protocol_type、service、flag和label。
为了做到这一点,我们使用fit.transform(),它校准我们的测量:
from sklearn import preprocessing
Data.protocol_type = preprocessing.LabelEncoder().fit_transform(Data["protocol_type"])
Data.service = preprocessing.LabelEncoder().fit_transform(Data["service"])
Data.flag = preprocessing.LabelEncoder().fit_transform(Data["flag"])
Data.label = preprocessing.LabelEncoder().fit_transform(Data["label"])
在 scikit-learn 中,有两种不同的方法:fit和fit_transform。这两种方法之间的区别在于,fit计算参数(μ和σ,其中μ是总体的平均值,σ是总体的标准差)并在内部保存它们,而fit_transform做同样的任务,但也对特定的样本集应用了转换。
让我们识别我们的数据。在下面的行中,我们使用了一个额外的 NumPy 方法as_matrix(),将框架转换为它的 NumPy 数组表示。在 NumPy 数组中,返回的不是 NumPy 矩阵,而是 NumPy 数组,根据官方文档的说法:
X = Data[Columns].as_matrix()
y = Data.label.as_matrix()
通常,在这一步之后,我们会进行模型训练;但这一次,我们将花更多时间来分析和可视化我们的数据和特征。数据科学的一个任务是获得洞察和知识,可视化对于数据科学和机器学习至关重要。我的建议是尽可能多地玩弄数据,并尝试不同的技术。正如你已经注意到的,机器学习系统通常遵循相同的技术,作为数据科学家或机器学习专家,你的工作是从数据中选择正确的特征。机器学习算法是基于数学的,通常情况下,你不会改变算法本身;相反,你会希望进行一些良好的特征工程,以构建一个可靠且准确度高的模型,以满足你的目标。
Yellowbrick 是一个很棒的可视化库和一套视觉诊断工具(可视化器)。这个库依赖于 scikit-learn 和 Matplotlib。你可以使用pip来安装它:
pip install yellowbrick
这个库非常丰富,让您可以可视化特征、分类、回归、聚类,甚至文本(例如,可视化语料库中术语的频率分布):
visualizer = Rank1D(features=Columns, algorithm='shapiro')
visualizer.fit(X, y)
visualizer.transform(X)
visualizer.poof()
visualizer.poof()将显示绘图如下:
要保存绘图,您可以添加outpath,就像下面这样:
visualizer.poof(outpath="Figure1.png")
您甚至可以将其导出为 PDF 文件。 您可能已经注意到,在visualizer = Rank1D(features=Columns, algorithm='shapiro')一行中,我们使用了一个名为Rank1D的方法和一个名为shapiro的算法,以对特征进行排名并检测它们之间的关系。 Rank1D和Rank2D评估单个特征或特征对。 在我们的案例中,我们使用了特征的一维排名。
Rank2D是特征的二维排名。 以下显示了如何实现它:
visualizer = Rank2D(features=Columns, algorithm='covariance')
您可以从pearson或covariance中进行选择:
visualizer.fit(X, y)
visualizer.transform(X)
visualizer.poof()
让我们回到我们使用的排名算法。 shapiro参数是指 Shapiro-Wilk 排名算法。 您可以选择您的排名算法:
我们之前发现了主成分分析(PCA)。 Yellowbrick 使您能够将高维数据分解为二维或三维,并将其绘制出来:
visualizer = PCADecomposition(scale=True, center=False, col=y)
visualizer.fit_transform(X,y)
visualizer.poof()
此外,绘图可以是 3D 的:
visualizer = PCADecomposition(scale=True, center=False, color=y, proj_dim=3)
visualizer.fit_transform(X,y)
visualizer.poof()
上述代码在此图中呈现:
现在是时候训练我们的入侵检测机器学习模型了。 与往常一样,我们拆分数据,选择使用的分类器,拟合模型并获得评分结果:
clf = RandomForestClassifier(max_depth=2, random_state=0)
clf.fit(X, y)
Score = clf.score(X_test,y_test)
print(Score*100)
我们入侵检测系统的得分为 85.7%。 有关更多详细信息,您可以输出评估指标(TF,FP,TN,FN 和 Recall),就像在以前的模型中所做的那样。
Kale 堆栈
监控是一项艰巨的任务,特别是在涉及数百名工程师的团队中,可能会发生指标过载。 为了解决这个问题,除了基于时间序列的异常检测能力之外,还有许多项目可以使用。 其中之一是 Kale 堆栈。 它由两部分组成:Skyline 和 Oculus。 Skyline 的作用是检测异常指标(异常检测系统),而 Oculus 是异常相关组件。 要下载这两个组件,您可以查看以下存储库:
-
Skyline:
github.com/etsy/skyline -
Oculus:
github.com/etsy/oculus
您将需要以下内容:
-
至少 8 GB RAM
-
四核 Xeon 5620 CPU,或同等配置
-
1 GB 磁盘空间
总结
在本章中,我们探讨了网络异常检测技术的基础知识以及其背后的理论。 您学会了如何使用 Python 构建基于机器学习的网络异常检测器。 您可以使用许多其他技术来构建机器学习 IDS。 下一章将通过引导您部署一个完全工作的威胁猎杀平台来增强您的技能,该平台使用了一个名为 ELK stack 的开源项目堆栈。
问题
-
什么是异常?
-
马尔可夫链是什么?
-
隐藏的马尔可夫模型是什么?
-
我们如何使用隐藏的马尔可夫模型检测异常?
-
时间序列异常检测与其他类型的异常检测有什么区别?
-
时间序列异常检测与其他类型的异常检测有什么区别?
-
监督和无监督机器学习异常检测有什么区别?
进一步阅读
-
博客文章:
-
DevOps 异常检测实用指南:
www.bigpanda.io/blog/a-practical-guide-to-anomaly-detection/ -
论文:
-
基于时序异常的根本原因分析,通过分布式复杂系统中的时空图形建模:
arxiv.org/abs/1805.12296 -
一种用于无监督异常检测的广义主动学习方法:
arxiv.org/abs/1805.09411 -
朝向异常的解释:一类模型的深度泰勒分解:
arxiv.org/abs/1805.06230 -
朝着高效的基于异常的软件定义网络入侵检测:
arxiv.org/abs/1803.06762
第七章:检测高级持续威胁
现代组织每天都面临网络威胁。黑帽黑客并没有显示出他们要停止的迹象。新的黑客技术经常出现。检测高级持续威胁(APT)是一项艰巨的任务,因为这些攻击的目标是长时间保持不被发现,并窃取数据,而不是对系统造成损害。
根据多份信息安全报告,APT 攻击的数量正在显著增加,瞄准国家防御、制造业和金融行业。因此,传统的保护技术在许多情况下是无用的。部署合适的平台和解决方案可以帮助组织和公司抵御网络攻击,特别是 APT 攻击。
本章将为您提供逐步指导,教您如何构建威胁狩猎平台,使用一系列知名的开源项目来保护您的客户数据。您将学习如何创建一个机器学习模块来增强您的平台,并自动检测异常,以便您可以专注于团队内的其他问题。
在本章中,我们将涵盖:
-
高级威胁格局
-
威胁狩猎方法论
-
狩猎成熟度模型
-
网络杀伤链
-
入侵检测的钻石模型
-
使用机器学习进行威胁狩猎,使用Elasticsearch、Logstash和Kibana(ELK)堆栈
技术要求
在本章中,我们将使用在前几章中使用过的相同的 Python 库。建议您具备以下内容:
-
4 GB RAM
-
2 GB CPU
威胁和风险分析
威胁是对您组织资产的潜在危险。根据 2017 年欧洲网络和信息安全局(ENISA)威胁形势报告,现代组织面临着数百万的网络威胁,包括:恶意软件、基于网络的攻击、网络钓鱼、勒索软件、僵尸网络等。对于安全专业人员,尤其是风险管理人员,威胁在分析风险中起着巨大的作用。风险是威胁和漏洞的组合,可以用数学表示为风险=威胁 x 漏洞。
威胁狩猎方法论
威胁狩猎是一种寻找、识别和理解 APT 的方法。威胁狩猎,就像任何方法论的信息安全任务一样,不是关于工具和实用程序。它是一种过程、人员和技术的结合。
威胁狩猎涉及以下步骤:
-
创建假设
-
使用工具和技术进行调查
-
发现新的模式
-
信息和丰富的分析
以下步骤构成了威胁狩猎循环:
您可以通过从以下选择一个级别来评估您的威胁狩猎计划的成熟度:
-
等级 1:初始(几乎没有数据收集,依赖自动警报)
-
等级 2:最低(高水平的数据收集)
-
等级 3:程序化(高水平的数据收集,遵循数据分析程序)
-
等级 4:创新(高水平的数据收集,遵循新的数据分析程序)
-
等级 5:领先(高水平的数据收集,自动化成功的数据分析程序)
以下两个部分包括威胁狩猎中最重要的术语。
网络杀伤链
像信息安全的许多方面一样,网络杀伤链是一个受军事启发的模型,用于描述网络攻击中使用的步骤。
网络杀伤链的七个步骤如下:
-
侦察:收集信息,如电子邮件地址
-
武器化:将漏洞与后门结合到可交付的有效载荷中,换句话说,使用漏洞和后门构建可交付的有效载荷
-
交付:通过不同方式向受害者交付武器化的捆绑包,例如电子邮件或 USB
-
利用:利用漏洞在目标机器上执行代码
-
安装:安装恶意软件
-
命令和控制(C2):远程操纵受害者的命令通道
-
行动和目标:完成原始目标
入侵分析的钻石模型
入侵分析的钻石模型是一种用于验证网络威胁的方法论。每个事件都可以表示为一个钻石。许多信息安全分析师使用这种认知模型来一致地表征有组织的威胁,并在其演变过程中跟踪它们。
钻石的四个节点如下:
-
对手(坏人角色)
-
基础设施(如 IP 地址、域名和电子邮件地址)
-
能力(如恶意软件、漏洞利用和被盗证书)
-
受害者(如人员和网络资产)
使用 ELK Stack 进行威胁狩猎
您现在已经清楚地了解了威胁狩猎中最重要的术语。因此,让我们构建我们的威胁狩猎平台。在接下来的几节中,我们将学习如何使用开源项目构建威胁狩猎系统。在我们的实践指南中,我们将使用其中一个最有前途的解决方案——ELK Stack。它包括三个开源项目,是当今最受欢迎的日志管理平台之一。
ELK Stack 广泛应用于许多领域,包括:
-
商业智能
-
网络分析
-
信息安全
-
合规性
ELK Stack 由以下组件组成:
-
Elasticsearch:搜索和分析数据
-
Logstash:收集和转换数据
-
Kibana:可视化数据
以下图表说明了 ELK Stack 中的主要组件:
因此,根据主要架构,为了构建威胁狩猎平台,我们需要:收集日志,分析和搜索合适的数据,并管理我们发现的可视化。让我们看看如何准备 ELK Stack 环境。
Elasticsearch
Elasticsearch 是一个令人惊叹的开源项目。它是一个基于 RESTful、分布式和基于 JSON 的搜索引擎。换句话说,您可以将其视为 NoSQL 搜索服务器。您可以在其官方网站上查看:www.elastic.co/
要下载它,转到www.elastic.co/downloads/elasticsearch
选择合适的软件包。在我的情况下,我将在 Ubuntu 14.04 机器上安装它。因此,我将选择.deb版本。建议您具有以下内容:
-
4GB RAM
-
2GB CPU
Elasticsearch 是用 Java 编写的。因此,我们需要确保它已安装在我们的环境中(如果没有,则应下载)。将 Java 添加到apt如下:
sudo add-apt-repository -y ppa:webupd8team/java
现在 Java 源已添加到list.sources文件中:
更新list.sources文件:
现在,安装 Java installer:
sudo apt-get -y install oracle-java8-installer
然后,进行配置:
太好了!我们已经成功安装了。通过输入java -version命令来检查:
让我们安装 Elasticsearch。导入elasticsearch公钥如下:
wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo
apt-key add -
将 Elasticsearch 添加到源列表中:
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" |
sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
通过使用apt-get update和install elasticsearch来更新源列表:
apt-get install elasticsearch
要配置 Elasticsearch,使用文本编辑器编辑/etc/elasticsearch/elasticsearch.yml:
vi /etc/elasticsearch/elasticsearch.yml
配置文件后,重新启动 Elasticsearch 服务:
sudo service elasticsearch restart
Kibana
安装和配置 Elasticsearch 后,是时候安装 Kibana 了,以在设计良好的仪表板中可视化数据。Kibana 是一个带有不同类型图表的 Web 界面。您可以将其视为我们堆栈的可视化层。
像往常一样使用apt-get install命令安装 Kibana:
apt-get install kibana
安装不会花费太长时间:
安装完成后,我们可以使用文本编辑器配置它,修改/opt/kibana/config/kibana.yml配置文件:
sudo vi /opt/kibana/config/kibana.yml
使用以下命令启用 Kibana 服务:
sudo update-rc.d kibana defaults 96 9
使用以下命令启动服务:
sudo service kibana start
如果您想要使用公共 IP 地址从外部访问仪表板,您可以使用反向代理。例如,在这种情况下,Nginx将是一个很好的选择。
您可以在/usr/share/kibana找到 Kibana 文件夹:
要检查仪表板,请输入<Address>: 5601并输入您的凭据:
Logstash
此时,我们已经安装了 Elasticsearch 和 Kibana;现在我们需要安装 Logstash 来收集和转换数据。Logstash 管道包含三个组件:
-
输入
-
过滤器
-
输出
让我们将 Logstash 添加到源列表中,然后更新它:
echo 'deb http://packages.elastic.co/logstash/2.2/debian stable main' |
sudo tee /etc/apt/sources.list.d/logstash-2.2.x.list
按照以下方式安装 Logstash:
apt-get install logstash
安装 Logstash 后,您可以编辑其配置文件<Parent_Directory>/logstash/conf/logstash.conf。正如您将注意到的那样,配置文件包含两个部分 - input 和 output:
等等!我打赌您一定想知道为什么我们只有两个部分,尽管 Logstash 包含三个部分,就像我们之前讨论的那样。您完全正确。我们需要添加一个自定义部分,称为filters。Logstash 提供了很好的功能,包括创建个性化过滤器的能力。例如,要创建一个过滤器,您可以使用以下格式(我们将在我们的指南中稍后使用它):
filter {
grok {
match => { "message" => "COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent}" }
}
date {
match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
gork过滤器用于将非结构化的日志数据解析为结构化且可查询的数据。根据官方的过滤器插件部分(www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html),Logstash 默认提供了 120 多种模式。
使用 X-Pack 插件进行 ELK Stack 的机器学习
我们现在已经安装了 ELK Stack 的三个主要组件。如果您想要一种有效的部署 ELK Stack 的方式,特别是用于测试目的,我建议您使用基于云的堆栈。例如,在以下演示中,我将使用 Bitnami 预定义的云 ELK Stack。
Bitnami ELK Stack 随附以下软件版本:
-
Apache 2.4.29
-
Elasticsearch 6.2.2
-
Logstash 6.2.2
-
Kibana 6.2.2
在几分钟内,您的堆栈将准备就绪。以下屏幕截图显示了 ELK Stack 文件:
要获取 Bitnami 环境的密码,请转到 Azure 门户中的 Boot 诊断部分,并检查日志文件;您将在文件底部找到密码:
在添加机器学习插件之前,让我们配置我们的 ELK Stack。使用以下命令加载 ELK 环境并登录到 ELK 服务器:
sudo /opt/bitnami/use_elk
让我们通过输入sudo /opt/bitnami/ctlscript.sh stop logstash来停止 Logstash
创建一个配置文件/opt/bitnami/logstash/conf/access-log.conf:
input {
file {
path => "/opt/bitnami/apache2/logs/access_log"
start_position => beginning
}
}
filter {
grok {
match => { "message" => "COMBINEDAPACHELOG %{COMMONAPACHELOG} %{QS:referrer} %{QS:agent}" }
}
date {
match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
output {
elasticsearch {
hosts => [ "127.0.0.1:9200" ]
}
}
检查/opt/bitnami/logstash/bin/logstash -f /opt/bitnami/logstash/conf/ --config.test_and_exit的配置:
按照以下方式启动 Logstash:
sudo /opt/bitnami/ctlscript.sh start logstash
检查 Elasticsearch 是否正常工作:
现在,让我们去 Kibana。正如您可能已经注意到的,我们还没有索引模式:
配置 Logstash 后,我们可以创建一个新的索引模式:
输入*并点击下一步:
选择@timestamp 并点击Create Index pattern按钮。您现在可以在 Kibana 中查看新的索引模式页面:
当您点击 Discover 选项时,您可以检查日志:
现在,让我们自定义一个可添加到主仪表板的可视化。在侧边栏上点击可视化,然后创建一个新的可视化:
对于我们的演示,我们将使用垂直条形图。您可以从一系列图表和可视化工具中进行选择:
对于 X 轴,选择日期直方图作为聚合和@timestamp 作为字段:
然后,您将看到您图表的可视化,如下面的截图所示:
创建可视化后,让我们添加到我们的仪表板。点击仪表板链接并创建一个新的仪表板。然后,添加您的可视化:
保存仪表板。现在,您可以检查任何指标:
ELK Stack 威胁平台已准备好帮助您追踪多种高级威胁。让我们将项目提升一个档次,并通过利用机器学习的力量来自动化追踪操作,为其增加智能化的触角。ELK Stack 让您有能力向您的追踪平台添加一个名为 X-Pack 的插件,它将帮助您检测您的文物和日志中的异常。
要获得 X-Pack 插件,我们需要在堆栈的每一层上安装它,正如官方插图所示:
要在 Elasticsearch 上安装插件,请转到binaries文件夹,并输入以下命令:
./elasticsearch-plugin install x-pack
相同的操作也适用于 Kibana:
sudo bin/kibana-plugin install x-pack
这也适用于 Logstash:
sudo bin/logstash-plugin install x-pack
重新启动所有服务并转到 Kibana 仪表板;您将注意到一个新选项,称为机器学习:
最后,由于 X-Pack,您可以添加时间序列异常检测功能。在上一章中,我们详细讨论了异常检测。我们深入研究了异常检测的基本原理以及如何使用机器学习来检测这些异常。X-Pack 正在使用相同的技术来发现异常。
总结
在之前的章节中,我们看到如何使用不同的机器学习算法和 Python 库从头开始构建异常检测系统。本章包括了一份逐步指南,帮助您构建一个完全功能的威胁追踪平台,使用了三个令人惊叹的开源项目。我们还实施了一个机器学习插件,以优化和增强威胁追踪平台的能力。到目前为止,您已经学会了如何使用机器学习的力量构建许多防御系统。如果您想学习如何绕过机器学习保障,下一章是必读的。
问题
- 以下哪一项不是网络攻击杀伤链中的步骤?
(a)扫描
(b)控制和命令
(c)发现和传播
- 以下哪个选项不是入侵分析钻石模型的节点?
(a)受害者
(b)基础设施
(c)程序
- Logstash 配置文件需要多少部分?
(a)2
(b)3
(c)4
- 在 Elasticsearch 中,索引是什么?
(a)在索引中存储数据的过程
(b)识别数据的过程
(c)以上都不是
- 在 Elasticsearch 中,什么是节点?
(a)Elasticsearch 模块
(b)Elasticsearch 的一个实例
(c)以上都不是
- 在 Elasticsearch 中,什么是分片?
(a)共享文件
(b)共享数据
(c)共享资源(RAM、vCPU 等)
- Elasticsearch 有模式吗?(是 | 否)
第八章:规避入侵检测系统
部署入侵检测系统对于每家现代公司来说都是必不可少的,以防御攻击者。在前几章中,我们学习了如何构建基于机器学习的入侵检测系统。现在,是时候学习如何通过对抗学习来绕过这些系统了;为了保护您的系统,您需要先学会如何攻击它们。
在本章中,我们将涵盖以下内容:
-
对抗机器学习算法
-
机器学习威胁模型
-
使用对抗网络系统规避入侵检测系统
技术要求
在本章中,您将需要以下库:
-
PyYAML
-
NumPy
-
SciPy
-
CVXPY
-
Python 3
-
Matplotlib
-
scikit-learn
-
进展
-
Pathos
-
CVXOPT(作为 CVXPY 求解器的可选项)
-
Jupyter Notebook
您可以在以下网址找到代码文件:github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter08。
对抗机器学习算法
在学习对抗机器学习之前,让我们探讨两个重要的术语:过拟合和欠拟合。
过拟合和欠拟合
过拟合是机器学习从业者面临的最大障碍之一。知道如何发现过拟合是构建健壮的机器学习模型所必需的技能,因为达到 99%的准确率并不是故事的结束。在机器学习中,我们进行预测。根据定义,拟合是我们对目标函数的逼近程度。正如我们在第一章中看到的,监督学习的目标是映射输入数据和目标之间的函数。因此,一个良好的拟合是对该函数的良好逼近。
过拟合发生在模型学习训练数据中的细节和噪音,以至于负面影响了模型的性能。换句话说,模型学习到了噪音,因此在输入新数据时无法很好地进行泛化。下图说明了过拟合的情况。您会注意到模型已经训练得太好,这使得在向模型输入数据时很难实现准确性。
另一个障碍是欠拟合。当机器学习模型不足够拟合数据时就会发生这种情况。换句话说,当模型过于简单时:
使用 Python 进行过拟合和欠拟合
让我们用 scikit-learn 来看一下过拟合和欠拟合的真实演示。导入所需的模块:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
我们现在将构建一个小模型,并可视化模型、样本和true函数,以查看过拟合和欠拟合。我们将使用以下代码:
np.random.seed(0)
n_samples = 30
degrees = [1, 4, 15]
X = np.sort(np.random.rand(n_samples))
y = np.cos(1.5 * np.pi * X) + np.random.randn(n_samples) * 0.1
plt.figure(figsize=(14, 5))
for i in range(len(degrees)):
ax = plt.subplot(1, len(degrees), i + 1)
plt.setp(ax, xticks=(), yticks=())
polynomial_features = PolynomialFeatures(degree=degrees[i],
include_bias=False)
linear_regression = LinearRegression()
pipeline = Pipeline([("polynomial_features", polynomial_features),
("linear_regression", linear_regression)])
pipeline.fit(X[:, np.newaxis], y)
# Evaluate the models using crossvalidation
scores = cross_val_score(pipeline, X[:, np.newaxis], y,
scoring="neg_mean_squared_error", cv=10)
X_test = np.linspace(0, 1, 100)
plt.plot(X_test, pipeline.predict(X_test[:, np.newaxis]), label="Model")
plt.plot(X_test, true_fun(X_test), label="True function")
plt.scatter(X, y, edgecolor='b', s=20, label="Samples")
plt.xlabel("x")
plt.ylabel("y")
plt.xlim((0, 1))
plt.ylim((-2, 2))
plt.legend(loc="best")
plt.title("Degree {}\nMSE = {:.2e}(+/- {:.2e})".format(
degrees[i], -scores.mean(), scores.std()))
plt.show()
通过运行前面的脚本,我们绘制了以下图表,说明了 3 种情况:欠拟合、良好拟合和过拟合(从左到右):
以下表格是使用前面代码中突出显示的术语和相应的 URL 创建的:
检测过拟合
为了检测过拟合,强烈建议将初始数据集分成训练集和测试集。如果训练集的表现远远好于测试集,那么我们就有问题。此外,强烈建议从简单的算法开始,然后再转向更复杂的模型,检查升级复杂度是否值得。为了防止过拟合,我们可以使用交叉验证。交叉验证是通过使用不同子集(k子集)训练模型来评估许多机器学习技术的过程。
对抗机器学习
对抗机器学习是研究如何破解和保护机器学习模型的艺术。您可以将其视为机器学习和信息安全之间的交集。作为安全专业人士,学习如何使用机器学习构建防御层很重要,但了解如何破解它们也是您技能组合的一个很棒的补充:
2006 年,Barreno 等人提出了针对机器学习系统的威胁模型的分类法。该模型基于三个轴:
-
影响
-
安全违规
-
特异性
2011 年,黄等人扩展了该模型,包括另一个称为隐私的轴。2016 年,Papernot,McDaniel,Jha,Fredrikson,Celik 和 Swami 引入了一个专注于两个轴的新分类法:
-
攻击的复杂性
-
攻击者的知识
以下图表说明了机器学习威胁分类:
为了攻击机器学习模型,攻击者可以执行许多技术,这些技术在以下部分中进行了讨论。
规避攻击
为执行机器学习规避攻击,网络犯罪分子尝试通过观察模型的工作方式,尤其是结果,尝试许多不同的样本,只需向模型提供不同的输入并尝试找到学习模式。这种技术非常流行。例如,如果攻击者想要规避机器学习垃圾邮件过滤器,他需要向系统提供不同的电子邮件并搜索使垃圾邮件通过(未被检测为垃圾邮件)并通过仅对先前检测到的电子邮件进行少量修改来规避检测的模式。
以下工作流说明了规避攻击的工作原理:
毒害攻击
在机器学习中毒攻击中,攻击者通过在模型训练阶段添加恶意数据来毒害模型,以改变学习结果。例如,可以通过在网络操作期间进行数据收集时发送和注入精心设计的样本来执行此方法,以训练网络入侵检测系统模型。以下工作流说明了毒害攻击的发生过程:
在意大利模式识别与应用实验室进行的一些最重要的对抗机器学习研究包括针对支持向量机的毒害攻击,当 Battista Biggio 及其团队提出了一个攻击支持向量机系统的重要框架。步骤如下:
-
确定适当的对手目标
-
定义对手的知识
-
制定相应的优化问题
-
相应地重新采样收集的(训练和测试)数据
-
评估在重新采样数据上的分类器安全性
-
针对不同水平的对手知识重复评估
如果您熟悉 MATLAB,我强烈建议您尝试ALFASVMLib。这是一个关于 SVM 上对抗性标签翻转攻击的 MATLAB 库。您可以从github.com/feuerchop/ALFASVMLib下载它。
对抗聚类
聚类技术广泛应用于许多实际应用中。攻击者正在提出新的技术来攻击聚类模型。其中之一是对抗聚类,攻击者通过操纵输入数据(添加少量攻击样本),使新添加的样本可以隐藏在现有的聚类中。
对抗特征
特征选择是每个机器学习项目中的重要步骤。攻击者也在使用对抗性特征选择来攻击模型。我强烈建议您阅读同一团队(意大利模式识别与应用实验室研究人员)在一篇名为*特征选择对训练数据毒害是否安全?*的论文中所做的研究。
团队表明,通过污染嵌入式特征选择算法,包括 LASSO、岭回归和 ElasticNet,他们愚弄了 PDF 恶意软件检测器。
有许多 Python 框架和开源项目是由研究人员开发的,用于攻击和评估机器学习模型,例如CleverHans,对抗机器学习(AML)库和EvadeML-Zoo。
CleverHans
CleverHans 正在不断发展; 它是一个对抗性示例库,用于构建攻击、构建防御和评估机器学习系统对对抗性攻击的脆弱性。
您可以从github.com/tensorflow/cleverhans克隆它:
或者,您可以使用pip实用程序进行安装,如下所示:
AML 库
AML 库是由范德堡大学计算经济研究实验室开发的博弈论对抗机器学习库。 通过博弈论,我们指的是智能决策代理之间合作的数学模型的研究。 您可以从github.com/vu-aml/adlib克隆该库。
EvadeML-Zoo
EvadeML-Zoo 是由弗吉尼亚大学的机器学习组和安全研究组开发的对抗机器学习基准测试和可视化工具。 您可以从github.com/mzweilin/EvadeML-Zoo下载它。
使用对抗网络系统规避入侵检测系统
到目前为止,您已经对对抗性机器学习有了相当的了解,以及如何攻击机器学习模型。 现在是时候深入了解更多技术细节,学习如何使用 Python 绕过基于机器学习的入侵检测系统。 您还将学习如何防御这些攻击。
在这个演示中,您将学习如何使用污染攻击攻击模型。 正如之前讨论的,我们将注入恶意数据,以便影响模型的学习结果。 以下图表说明了污染攻击的发生方式:
在这次攻击中,我们将使用基于雅可比显著图攻击(JSMA)。 这是通过仅修改输入中有限数量的像素来搜索对抗性示例。
让我们看看如何使用 Python 攻击基于机器的入侵检测系统。 代码有点长,所以我只会包含一些重要的片段;稍后,您可以在本章的 GitHub 存储库中找到完整的代码。
对于这个项目,我们需要 NumPy、pandas、Keras、CleverHans、TensorFlow、scikit-learn 和 matplotlib Python 库。
这些是一些导入的库:
import numpy as np
import pandas as pd
from keras.models import Sequential
from keras.layers import Dense , Dropout
from keras.optimizers import RMSprop , adam
from cleverhans.attacks import fgsm , jsma
from cleverhans.utils_tf import model_train , model_eval , batch_eval
from cleverhans.attacks_tf import jacobian_graph
from cleverhans.utils import other_classes
import tensorflow as tf
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score , roc_curve , auc , f1_score
from sklearn.preprocessing import LabelEncoder , MinMaxScaler
import matplotlib.pyplot as plt
下一步是预处理数据:
names = ['duration', 'protocol', 'service ', 'flag', 'src_bytes', 'dst_bytes', 'land',
'wrong_fragment ','urgent ', 'hot', 'num_failed_logins ', 'logged_in ', 'num_compromised ', 'root_shell ', 'su_attempted ','num_root ', 'num_file_creations ', 'num_shells ', 'num_access_files ', 'num_outbound_cmds ','is_host_login ', 'is_guest_login ', 'count', 'srv_count ', 'serror_rate', 'srv_serror_rate ','rerror_rate ', 'srv_rerror_rate ', 'same_srv_rate ', 'diff_srv_rate', 'srv_diff_host_rate ','dst_host_count ', 'dst_host_srv_count ', 'dst_host_same_srv_rate ', 'dst_host_diff_srv_rate ','dst_host_same_src_port_rate ', 'dst_host_srv_diff_host_rate ', 'dst_host_serror_rate ','dst_host_srv_serror_rate ','dst_host_rerror_rate ', 'dst_host_srv_rerror_rate ','attack_type ', 'other ']
然后,我们将使用 pandas 加载数据:
TrainingData = pd.read_csv('KDDTrain+.txt', names=names , header=None)
TestingData = pd.read_csv('KDDTest+.txt', names=names , header=None)
然后,连接训练和测试集:
All = pd.concat ([TrainingData, TestingData])
assert full.shape[0] == TrainingData.shape[0] + TestingData.shape[0]
选择数据并识别特征:
All['label'] = full['attack_type']
要识别 DoS 攻击,请使用以下内容:
All.loc[All.label == 'neptune ', 'label'] = 'dos'
All.loc[All.label == 'back', 'label '] = 'dos'
All.loc[All.label == 'land', 'label '] = 'dos'
All.loc[All.label == 'pod', 'label'] = 'dos'
All.loc[All.label == 'smurf ', 'label'] = 'dos'
All.loc[All.label == 'teardrop ', 'label '] = 'dos'
All.loc[All.label == 'mailbomb ', 'label '] = 'dos'
All.loc[All.label == 'processtable ', 'label'] = 'dos'
All.loc[All.label == 'udpstorm ', 'label '] = 'dos'
All.loc[All.label == 'apache2 ', 'label'] = 'dos'
All.loc[All.label == 'worm', 'label '] = 'dos'
使用相同技术识别其他攻击(User-to-Root(U2R)、Remote-to-Local(R2L)和Probe)。
要生成一热编码,请使用以下内容:
full = pd.get_dummies(All , drop_first=False)
再次识别训练和测试集:
features = list(full.columns [:-5])
y_train = np.array(full[0:TrainingData.shape[0]][[ 'label_normal ', 'label_dos ', 'label_probe
label_r2l ', 'label_u2r ']])
X_train = full[0:TrainingData.shape[0]][ features]
y_test = np.array(full[TrainingData.shape[0]:][[ 'label_normal ', 'label_dos ', 'label_probe ', '
label_r2l ', 'label_u2r ']])
X_test = full[TrainingData.shape[0]:][features]
要缩放数据,请使用以下命令:
scaler = MinMaxScaler().fit(X_train)
scale X_train的示例如下:
X_train_scaled = np.array(scaler.transform(X_train))
假设我们要攻击逻辑回归模型; 我们需要处理数据以训练该模型并生成标签编码:
labels = All.label.unique()
En = LabelEncoder()
En.fit(labels)
y_All = En.transform(All.label)
y_train_l = y_All[0:TrainingData.shape[0]]
y_test_l = y_All[TrainingData.shape[0]:]
我们现在已经完成了预处理阶段。
对于基于雅可比显著图攻击,我们将使用以下 Python 实现:
results = np.zeros((FLAGS.nb_classes , source_samples), dtype='i')
perturbations = np.zeros((FLAGS.nb_classes , source_samples), dtype='f')
grads = jacobian_graph(predictions , x, FLAGS.nb_classes)
X_adv = np.zeros(( source_samples , X_test_scaled.shape [1]))
for sample_ind in range(0, source_samples):
current_class = int(np.argmax(y_test[sample_ind ]))
for target in [0]:
if current_class == 0:
Break
adv_x , res , percent_perturb = jsma(sess , x, predictions , grads,X_test_scaled[sample_ind: (sample_ind+1)],target , theta=1, gamma =0.1,increase=True , back='tf',clip_min=0, clip_max =1)
X_adv[sample_ind] = adv_x
results[target , sample_ind] = res
perturbations[target , sample_ind] = percent_perturb
要构建MultiLayer Perceptron网络,请使用以下代码片段:
def mlp_model ():
Generate a MultiLayer Perceptron model
model = Sequential ()
model.add(Dense (256, activation='relu', input_shape =( X_train_scaled.shape [1],)))
model.add(Dropout (0.4))
model.add(Dense (256, activation='relu'))
model.add(Dropout (0.4))
model.add(Dense(FLAGS.nb_classes , activation='softmax '))model.compile(loss='categorical_crossentropy ',optimizer='adam',metrics =['accuracy '])
model.summary ()
return model
对于对抗性预测,请使用以下内容:
y_pred_adv = dt.predict(X_adv)
fpr_dt_adv , tpr_dt_adv , _ = roc_curve(y_test[:, 0], y_pred_adv [:, 0])
roc_auc_dt_adv = auc(fpr_dt_adv , tpr_dt_adv)
print("Accuracy score adversarial:", accuracy_score(y_test , y_pred_adv))
print("F1 score adversarial:", f1_score(y_test , y_pred_adv , average='micro '))
print("AUC score adversarial:", roc_auc_dt_adv)
最后,我们需要通过提供对抗性测试数据来评估模型:
如果出现错误,请检查本章的 GitHub 存储库。代码可能在出版后进行更新和增强。
摘要
在本章中,我们概述了对抗性学习技术,并描述了攻击者和网络犯罪分子如何对机器学习模型进行攻击。
下一章将是一个很好的补充指南,探讨如何攻击人工神经网络和深度学习网络。您将了解攻击者如何通过使用对抗性深度学习和强化学习来绕过现代反恶意软件系统。
问题
-
您能简要解释一下为什么过度训练机器学习模型不是一个好主意吗?
-
过拟合和欠拟合之间有什么区别?
-
规避攻击和中毒攻击之间有什么区别?
-
对抗性聚类是如何工作的?
-
用于规避入侵检测系统的对抗性攻击类型是什么?
-
前面的攻击是规避还是中毒攻击?
进一步阅读
-
人工智能的恶意使用:预测、预防和缓解:
img1.wsimg.com/blobby/go/3d82daa4-97fe-4096-9c6b-376b92c619de/downloads/1c6q2kc4v_50335.pdf -
使用对抗性示例攻击机器学习:
blog.openai.com/adversarial-example-research/ -
令人敬畏的对抗性机器学习:
github.com/yenchenlin/awesome-adversarial-machine-learning -
集成对抗训练:攻击和防御:
arxiv.org/pdf/1705.07204.pdf -
对抗性机器学习简介:
mascherari.press/introduction-to-adversarial-machine-learning/ -
对抗性深度学习对入侵检测分类器的攻击:
www.diva-portal.org/smash/get/diva2:1116037/FULLTEXT01.pdf -
特征选择是否能够抵御训练数据中毒? (
pralab.diee.unica.it/sites/default/files/biggio15-icml.pdf) -
AI 和安全威胁的通用框架:
img1.wsimg.com/blobby/go/3d82daa4-97fe-4096-9c6b-376b92c619de/downloads/1c6q2kc4v_50335.pdf -
机器学习验证和测试的挑战:
www.cleverhans.io/security/privacy/ml/2017/06/14/verification.html: -
入侵检测网络的攻击:规避、逆向工程和最佳对策(博士论文):
www.seg.inf.uc3m.es/~spastran/phd/PhD_Thesis_Sergio_Pastrana.pdf
第九章:绕过机器学习恶意软件检测器
在上一章中,您了解到可以通过使用对抗性机器学习技术攻击机器学习模型并使其执行恶意活动。在本章中,我们将进一步探讨如何欺骗人工神经网络和深度学习网络等技术。我们将以反恶意软件系统规避为案例研究。
在本章中,我们将涵盖以下内容:
-
对抗性深度学习
-
如何使用生成对抗网络绕过下一代恶意软件检测器
-
使用强化学习绕过机器学习
技术要求
本章的代码文件可以在github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter09找到。
对抗性深度学习
信息安全专业人员正在尽力提出新技术来检测恶意软件和恶意软件。其中一种流行的技术是使用机器学习算法来检测恶意软件。另一方面,攻击者和网络犯罪分子也在想出新方法来绕过下一代系统。在上一章中,我们看了如何攻击机器学习模型以及如何绕过入侵检测系统。
恶意软件开发人员使用许多技术来绕过机器学习恶意软件检测器。之前,我们探讨了一种通过使用灰度图像向量训练系统来构建恶意软件分类器的方法。在由** SARVAM **(恶意软件搜索和检索)研究单位在 UCSB 的 Vision Research Lab 进行的演示中,研究人员说明了通过更改几个字节,模型可以将恶意软件分类为良性软件。攻击者可以通过更改几个字节和像素来绕过恶意软件分类器执行此技术。在演示中,研究人员使用了 NETSTAT 程序的变体,这是一个显示网络连接的命令行网络实用工具。在下图中,左侧是NETSTAT.EXE恶意软件的表示,第二个被检测为良性软件。如您所见,两个程序之间的差异是不可察觉的(36,864 字节中的 88 字节:0.78%),在将两种文件类型转换为灰度图像并检查它们之间的差异后:
这种技术只是一个开始;在本章中,我们将深入探讨如何欺骗它们(在我们的案例中是恶意软件分类器的机器学习模型)执行恶意活动。
上一章是对对抗性机器学习的概述。我们了解了攻击者如何绕过机器学习。在本章中,我们将更深入地了解如何绕过基于机器学习的恶意软件检测器;在此之前,我们将学习如何欺骗人工神经网络并避开 Python、开源库和开源项目的深度学习网络。神经网络可以被对抗样本欺骗。对抗样本被用作神经网络的输入,以影响学习结果。由 Ian J. Goodfellow、Jonathon Shlens 和 Christian Szegedy(在 Google)进行的一项开创性研究项目,名为解释和利用对抗网络,显示了一小部分精心构造的噪音可以欺骗神经网络,使其认为输入的图像是长臂猿而不是熊猫,且置信度为 99.3%。神经网络最初认为提供的图像是熊猫,置信度为 57.7%,这是正确的;但在第二个例子中,欺骗网络后情况并非如此:
许多电子设备和系统依赖深度学习作为保护机制,包括人脸识别;想象一下攻击者可以对它们进行的攻击,并未授权地访问关键系统。
现在,让我们试图愚弄一个神经网络。我们将使用著名的 MNIST 数据集愚弄手写数字检测系统。在第四章中,使用深度学习进行恶意软件检测,我们学习了如何构建一个。为了演示,我们将愚弄 Michael Nielsen 的一个预训练神经网络。他使用了 5 万张训练图像和 1 万张测试图像。或者,您也可以使用自己的神经网络。您可以在本章的 GitHub 存储库中找到训练信息。文件名为trained_network.pkl;您还会找到 MNIST 文件(mnist.pkl.gz):
import network.network as network
import network.mnist_loader as mnist_loader
# To serialize data
import pickle
import matplotlib.pyplot as plt
import numpy as np
让我们检查模型是否训练良好。加载pickle文件。使用pickle.load()加载数据,并识别训练、验证和测试数据:
Model = pickle.load( open( "trained_network.pkl", "rb" ) ) trainData, valData, testData =mnist_loader.load_data_wrapper()
例如,要检查数字 2,我们将选择test_data[1][0]:
>>> data = test_data[1][0]
>>> activations = Model.feedforward(data)
>>> prediction = np.argmax(activations)
以下屏幕截图说明了前面的代码:
通过使用matplotlib.pyplot (plt)绘制结果以进一步检查:
>>> plt.imshow(data.reshape((28,28)), cmap='Greys')
>>> plt.show()
如您所见,我们生成了数字2,所以模型训练得很好:
一切都设置正确。现在,我们将用两种类型的攻击来攻击神经网络:有目标的和无目标的。
对于无目标攻击,我们将生成一个对抗样本,并使网络给出特定输出,例如6:
在这次攻击中,我们希望神经网络认为输入的图像是6。目标图像(我们称之为X)是一个784维向量,因为图像尺寸是28×28像素。我们的目标是找到一个向量*⃗x*,使成本C最小化,从而得到一个神经网络预测为我们目标标签的图像。成本函数C定义如下:
以下代码块是导数函数的实现:
def input_derivative(net, x, y):
""" Calculate derivatives wrt the inputs"""
nabla_b = [np.zeros(b.shape) for b in net.biases]
nabla_w = [np.zeros(w.shape) for w in net.weights]
# feedforward
activation = x
activations = [x] # list to store all the activations, layer by layer
zs = [] # list to store all the z vectors, layer by layer
for b, w in zip(net.biases, net.weights):
z = np.dot(w, activation)+b
zs.append(z)
activation = sigmoid(z)
activations.append(activation)
# backward pass
delta = net.cost_derivative(activations[-1], y) * \
sigmoid_prime(zs[-1])
nabla_b[-1] = delta
nabla_w[-1] = np.dot(delta, activations[-2].transpose())
for l in xrange(2, net.num_layers):
z = zs[-l]
sp = sigmoid_prime(z)
delta = np.dot(net.weights[-l+1].transpose(), delta) * sp
nabla_b[-l] = delta
nabla_w[-l] = np.dot(delta, activations[-l-1].transpose())
return net.weights[0].T.dot(delta)
要生成对抗样本,我们需要设定目标:
goal = np.zeros((10, 1))
goal[n] = 1
创建一个随机图像以进行梯度下降初始化,如下所示:
x = np.random.normal(.5, .3, (784, 1))
计算梯度下降,如下所示:
for i in range(steps):
# Calculate the derivative
d = input_derivative(net,x,goal)
x -= eta * d
return x
现在,您可以生成样本:
a = adversarial(net, n, 1000, 1)
x = np.round(net.feedforward(a), 2)
Print ("The input is:", str(x))
Print ("The prediction is", str(np.argmax(x)))
绘制对抗样本,如下所示:
plt.imshow(a.reshape(28,28), cmap='Greys')
plt.show()
在有目标的攻击中,我们使用相同的技术和相同的代码,但是我们在成本函数中添加了一个新项。因此,它将如下所示:
Foolbox
Foolbox 是一个用于评估机器学习模型鲁棒性的 Python 工具包。它受到许多框架的支持,包括以下:
-
TensorFlow
-
PyTorch
-
Theano
-
Keras
-
Lasagne
-
MXNet
要安装 Foolbox,请使用pip实用程序:
pip install foolbox
以下是一些 Foolbox 攻击:
-
基于梯度的攻击:通过在输入x周围线性化损失
-
梯度符号攻击(FGSM):通过计算梯度g(x0),然后寻找最小步长
-
迭代梯度攻击:通过在梯度方向上的小步骤中最大化损失g(x)
-
迭代梯度符号攻击:通过在上升方向上的小步骤中最大化损失sign(g(x))
-
DeepFool L2 攻击:通过计算每个类的最小距离d(ℓ, ℓ0),以达到类边界
-
DeepFool L∞攻击:类似于 L2 攻击,但最小化L∞-范数
-
基于 Jacobian 的显著性图攻击:通过计算每个输入特征的显著性分数
-
单像素攻击:通过将单个像素设置为白色或黑色
要使用 Foolbox 实施攻击,请使用以下方法:
import foolbox
import keras
import numpy as np
from keras.applications.resnet50 import ResNet50
keras.backend.set_learning_phase(0)
kmodel = ResNet50(weights='imagenet')
preprocessing = (np.array([104, 116, 123]), 1)
fmodel = foolbox.models.KerasModel(kmodel, bounds=(0, 255), preprocessing=preprocessing)
image, label = foolbox.utils.imagenet_example()
attack = foolbox.attacks.FGSM(fmodel)
adversarial = attack(image[:, :, ::-1], label)
如果您收到错误消息,ImportError('load_weights requires h5py.'),请通过安装h5py库来解决(pip install h5py)。
要绘制结果,请使用以下代码:
import matplotlib.pyplot as plt
plt.figure()
plt.subplot(1, 3, 1)
plt.title('Original')
plt.imshow(image / 255)
plt.axis('off')
plt.subplot(1, 3, 2)
plt.title('Adversarial')
plt.imshow(adversarial[:, :, ::-1] / 255) # ::-1 to convert BGR to RGB
plt.axis('off')
plt.subplot(1, 3, 3)
plt.title('Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(difference / abs(difference).max() * 0.2 + 0.5)
plt.axis('off')
plt.show()
Deep-pwning
Deep-pwning 是一个轻量级框架,用于实验机器学习模型,旨在评估其对抗性对抗有动机的对手。它被称为机器学习的 metasploit。您可以从 GitHub 仓库克隆它:github.com/cchio/deep-pwning。
不要忘记安装所有的要求:
pip install -r requirements.txt
以下是与 Deep-pwning 一起使用所需的 Python 库:
-
Tensorflow 0.8.0
-
Matplotlib >= 1.5.1
-
Numpy >= 1.11.1
-
Pandas >= 0.18.1
-
Six >= 1.10.0
EvadeML
EvadeML (evademl.org )是基于遗传编程的进化框架,用于自动查找能够逃避基于机器学习的恶意软件分类器检测的变体。它是由弗吉尼亚大学的机器学习组和安全研究组开发的。
要下载 EvadeML,请从github.com/uvasrg/EvadeML克隆它。
要安装 EvadeML,您需要安装这些必需的工具:
-
用于解析 PDF 的 pdfrw 的修改版本:
github.com/mzweilin/pdfrw -
Cuckoo Sandbox v1.2,作为预言机:
github.com/cuckoosandbox/cuckoo/releases/tag/1.2 -
目标分类器 PDFrate-Mimicus:
github.com/srndic/mimicus -
目标分类器 Hidost:
github.com/srndic/hidost
要配置项目,请复制模板,并使用编辑器进行配置:
cp project.conf.template project.conf
Vi project.conf
在运行主程序./gp.py之前,运行带有预定义恶意软件签名的集中式检测代理,如文档中所示:
./utils/detection_agent_server.py ./utils/36vms_sigs.pickle
选择几个良性 PDF 文件:
./utils/generate_ext_genome.py [classifier_name] [benign_sample_folder] [file_number]
要向逃避添加新的分类器,只需在./classifiers/中添加一个包装器。
使用生成对抗网络绕过下一代恶意软件检测器
2014 年,Ian Goodfellow、Yoshua Bengio 及其团队提出了一个名为**生成对抗网络(GAN)**的框架。生成对抗网络能够从随机噪声生成图像。例如,我们可以训练一个生成网络,从 MNIST 数据集生成手写数字的图像。
生成对抗网络由两个主要部分组成:生成器和鉴别器。
生成器
生成器以潜在样本作为输入;它们是随机生成的数字,并且它们被训练以生成图像:
例如,要生成手写数字,生成器将是一个完全连接的网络,它接受潜在样本并生成784个数据点,将它们重塑为28x28像素图像(MNIST 数字)。强烈建议使用tanh作为激活函数:
generator = Sequential([
Dense(128, input_shape=(100,)),
LeakyReLU(alpha=0.01),
Dense(784),
Activation('tanh')
], name='generator')
鉴别器
鉴别器只是一个使用监督学习技术训练的分类器,用于检查图像是否为真(1)或假(0)。它通过 MNIST 数据集和生成器样本进行训练。鉴别器将把 MNIST 数据分类为真实的,生成器样本分类为假的:
discriminator = Sequential([
Dense(128, input_shape=(784,)),
LeakyReLU(alpha=0.01),
Dense(1),
Activation('sigmoid')], name='discriminator')
通过连接两个网络,生成器和鉴别器,我们产生了一个生成对抗网络:
gan = Sequential([
generator,
discriminator])
这是生成对抗网络的高级表示:
要训练 GAN,我们需要训练生成器(鉴别器在后续步骤中设置为不可训练);在训练中,反向传播更新生成器的权重以生成逼真的图像。因此,要训练 GAN,我们使用以下步骤作为循环:
-
用真实图像训练鉴别器(鉴别器在这里是可训练的)
-
将鉴别器设置为不可训练
-
训练生成器
训练循环将持续进行,直到两个网络都无法进一步改进。
使用 Python 构建 GAN,请使用以下代码:
import pickle as pkl
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
batch_size = 100
epochs = 100
samples = []
losses = []
saver = tf.train.Saver(var_list=g_vars)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for e in range(epochs):
for ii in range(mnist.train.num_examples//batch_size):
batch = mnist.train.next_batch(batch_size)
batch_images = batch[0].reshape((batch_size, 784))
batch_images = batch_images*2 - 1
batch_z = np.random.uniform(-1, 1, size=(batch_size, z_size))
_ = sess.run(d_train_opt, feed_dict={input_real: batch_images, input_z: batch_z})
_ = sess.run(g_train_opt, feed_dict={input_z: batch_z})
train_loss_d = sess.run(d_loss, {input_z: batch_z, input_real: batch_images})
train_loss_g = g_loss.eval({input_z: batch_z})
print("Epoch {}/{}...".format(e+1, epochs),
"Discriminator Loss: {:.4f}...".format(train_loss_d),
"Generator Loss: {:.4f}".format(train_loss_g))
losses.append((train_loss_d, train_loss_g))
sample_z = np.random.uniform(-1, 1, size=(16, z_size))
gen_samples = sess.run(
generator(input_z, input_size, n_units=g_hidden_size, reuse=True, alpha=alpha),
feed_dict={input_z: sample_z})
samples.append(gen_samples)
saver.save(sess, './checkpoints/generator.ckpt')
with open('train_samples.pkl', 'wb') as f:
pkl.dump(samples, f)
使用 Python 构建 GAN,我们将使用 NumPy 和 TensorFlow。
MalGAN
为了生成恶意软件样本来攻击机器学习模型,攻击者现在正在使用 GAN 来实现他们的目标。使用我们之前讨论过的相同技术(生成器和鉴别器),网络犯罪分子对下一代反恶意软件系统进行攻击,甚至不知道使用的机器学习技术(黑盒攻击)。其中一种技术是 MalGAN,它是由魏伟胡和应潭从机器感知(MOE)重点实验室和机器智能系进行的名为“基于 GAN 的黑盒攻击生成对抗性恶意软件示例”的研究项目中提出的。MalGAN 的架构如下:
生成器通过接受恶意软件(特征向量m)和噪声向量z作为输入来创建对抗性恶意软件样本。替代检测器是一个多层前馈神经网络,它以程序特征向量X作为输入。它对程序进行良性程序和恶意软件之间的分类。
为了训练生成对抗网络,研究人员使用了这个算法:
While not converging do:
Sample a minibatch of Malware M
Generate adversarial samples M' from the generator
Sample a minibatch of Goodware B
Label M' and B using the detector
Update the weight of the detector
Update the generator weights
End while
生成的许多样本可能不是有效的 PE 文件。为了保留变异和格式,系统需要一个沙盒来确保功能得到保留。
生成对抗网络训练不能简单地产生出优秀的结果;这就是为什么需要许多技巧来实现更好的结果。Soumith Chintala、Emily Denton、Martin Arjovsky 和 Michael Mathieu 引入了一些技巧来获得改进的结果:
-
将图像归一化在*-1和1*之间
-
使用最大对数D作为损失函数,以优化G而不是最小化(log 1-D)
-
从高斯分布中抽样,而不是均匀分布
-
为真实和虚假构建不同的小批量
-
避免 ReLU 和 MaxPool,而使用 LeakyReLU 和平均池化
-
如果可能的话,使用深度卷积 GAN(DCGAN)
-
使用
ADAM优化器
通过强化学习绕过机器学习
在先前的技术中,我们注意到如果我们生成对抗性样本,特别是如果结果是二进制的,我们将面临一些问题,包括生成无效样本。信息安全研究人员提出了一种绕过机器学习反恶意软件系统的新技术。
强化学习
以前(特别是在第一章),我们探讨了不同的机器学习模型:监督、半监督、无监督和强化模型。强化机器学习模型是构建智能机器的重要方法。在强化学习中,代理通过与环境的交互来学习,根据状态和奖励函数选择最佳决策:
强化学习的一个著名例子是基于 AI 的 Atari Breakout。在这种情况下,环境包括以下内容:
-
球和砖块
-
移动挡板(左或右)
-
消除砖块的奖励
下图展示了用于教授模型如何玩 Atari Breakout 的强化模型的高级概述:
以 Atari Breakout 环境作为学习如何避开反恶意软件系统的类比,我们的环境将如下:
对于代理,它需要环境状态(一般文件信息、头信息、导入和导出函数、字符串等)来优化其性能和来自反病毒报告的奖励输入,以及结果行动(创建入口点和新部分,修改部分等)。换句话说,为了执行和学习,代理正在接受两个输入(状态和奖励)。
作为我们讨论的概念的实现,信息安全专业人员致力于 OpenAI 环境,以利用强化学习技术构建可以逃避检测的恶意软件。其中一个环境是Gym-malware。这个出色的环境是由 endgame 开发的。
OpenAI gym 包含一个开源的 Python 框架,由非营利性人工智能研究公司 OpenAI(openai.com/)开发,用于开发和评估强化学习算法。要安装 OpenAI Gym,请使用以下代码(您需要安装 Python 3.5+):
git clone https://github.com/openai/gym
cd gym
pip install -e
OpenAI Gym 加载了预先制作的环境。您可以在gym.openai.com/envs/上检查所有可用的环境:
CartPole-v0 environment:
import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000): # run for 1000 steps
env.render()
action = env.action_space.sampe() # pick a random action
env.step(action) # take action
要使用 Gym-malware 环境,您需要安装 Python 3.6 和一个名为LIEF的库,它可以通过输入以下内容来添加:
pip install https://github.com/lief-project/LIEF/releases/download/0.7.0/linux_lief-0.7.0_py3.6.tar.gz
从github.com/endgameinc/gym-malware下载 Gym-malware。将安装的 Gym-malware 环境移动到gym_malware/gym_malware/envs/utils/samples/。
要检查您是否在正确的目录中拥有样本,请输入以下内容:
python test_agent_chainer.py
此环境中可用的操作如下:
-
append_zero -
append_random_ascii -
append_random_bytes -
remove_signature -
upx_pack -
upx_unpack -
change_section_names_from_list -
change_section_names_to random -
modify_export -
remove_debug -
break_optional_header_checksum
总结
在本章中,我们继续学习如何绕过机器学习模型。在上一章中,我们发现了对抗机器学习;在这一延续中,我们探讨了对抗深度学习以及如何欺骗深度学习网络。我们查看了一些真实案例,以了解如何使用最先进的技术逃避反恶意软件系统。在接下来的最后一章中,我们将获得更多知识,学习如何构建强大的模型。
问题
-
生成对抗网络的组成部分是什么?
-
生成器和鉴别器之间有什么区别?
-
在生成对抗样本时,我们如何确保恶意软件对抗样本仍然有效?
-
进行一些研究,然后简要解释如何检测对抗样本。
-
强化学习与深度学习有何不同?
-
监督学习和强化学习之间有什么区别?
-
在强化学习中,代理如何学习?
进一步阅读
以下资源包含大量信息:
-
解释和利用对抗样本:
arxiv.org/pdf/1412.6572.pdf -
深入研究可转移对抗样本和黑盒攻击:
arxiv.org/pdf/1611.02770.pdf -
Foolbox-用于基准测试机器学习模型鲁棒性的 Python 工具包:
arxiv.org/pdf/1707.04131.pdf -
The Foolbox GitHub:
github.com/bethgelab/foolbox -
基于 GAN 的黑盒攻击生成对抗恶意软件示例:
arxiv.org/pdf/1702.05983.pdf -
恶意软件图像:可视化和自动分类:
arxiv.org/pdf/1702.05983.pdf -
SARVAM:恶意软件的搜索和检索:
vision.ece.ucsb.edu/sites/vision.ece.ucsb.edu/files/publications/2013_sarvam_ngmad_0.pdf -
SigMal:基于静态信号处理的恶意软件分类:
vision.ece.ucsb.edu/publications/view_abstract.cgi?416
第十章:机器学习和特征工程的最佳实践
在前几章中,我们学习了机器学习的基础知识,并学习了如何使用一套令人惊叹的开源 Python 库构建许多不同的 Python 项目。此外,我们深入研究了如何打破机器学习模型。
本章将通过说明项目各个方面的许多技巧和最佳实践,帮助您构建更好的模型。
在本章中,我们将涵盖以下内容:
-
机器学习中特征工程的深入概述
-
机器学习的最佳实践
技术要求
您可以在此章节的代码文件中找到此代码:github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter10。
机器学习中的特征工程
通过在本书中构建和开发所有项目和原型,您肯定已经注意到特征工程和特征选择对于每个现代数据科学产品,特别是基于机器学习的项目至关重要。根据研究,构建模型所花费的时间中,超过 50%的时间用于清理、处理和选择训练模型所需的数据。您有责任设计、表示和选择特征。
大多数机器学习算法无法处理原始数据。它们不够聪明。因此,需要特征工程,将原始状态的数据转换为算法可以理解和消化的数据。安德鲁·吴教授曾经说过:
“构建特征是困难的,耗时的,需要专业知识。‘应用机器学习’基本上就是特征工程。”
特征工程是数据准备阶段的一个过程,根据数据挖掘的跨行业标准流程:
“特征工程”本身并没有正式定义的术语。它将所有设计特征以构建智能系统的任务组合在一起。它在系统中扮演着重要的角色。如果您参加数据科学竞赛,我敢打赌您已经注意到,竞争者们都使用相同的算法,但获胜者表现最佳的是特征工程。如果您想提高数据科学和机器学习技能,我强烈建议您访问并参加www.kaggle.com:
在搜索机器学习资源时,您将面临许多不同的术语。为了避免混淆,我们需要区分特征选择和特征工程。特征工程将原始数据转换为合适的特征,而特征选择从工程化的数据中提取必要的特征。特征工程是选择所有特征的子集,而不包括冗余或无关的特征。
特征选择算法
为了使算法能够更快地训练,并减少模型的复杂性和过拟合,除了提高准确性之外,您可以使用许多特征选择算法和技术。我们将看一下三种不同的特征选择方法:过滤方法、包装方法和嵌入方法。让我们讨论各种方法和技术。
过滤方法
在过滤方法中,每个特征将被分配一个分数,由不同的统计量计算得出。换句话说,这些方法通过考虑特征与目标之间的关系来对特征进行排名。过滤方法通常用于预处理阶段:
皮尔逊相关系数
Pearson 相关是一种用于测量两个变量x和y之间线性相关的统计方法。它的范围在+1和-1之间;+1表示有正相关。你需要知道x和y应该是连续变量。Pearson 相关系数的公式如下:
Cov是协方差,dx和dy是x和y的标准差:
要使用 Python 计算这个,你可以使用scipy.stats.pearsonr(x, y),来自scipy库。
线性判别分析
在以前的章节中,特别是在第一章,渗透测试中的机器学习简介中,我们看到了主成分分析(PCA)的统计程序。线性判别分析(LDA)也是一种降维技术。它用于找到将类别分开的特征的线性组合:
要在 scikit-learn 中使用 LDA,请使用以下行导入:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
使用方法如下:
sklearn_lda = LDA(n_components=2)
X_lda_sklearn = sklearn_lda.fit_transform(X, y)
方差分析
方差分析(ANOVA)类似于 LDA,但它使用分类特征来检查几个类的均值是否相等,通过分析它们之间的差异。
卡方
卡方用于确定子集数据是否与总体相匹配。值应该是在类别中。换句话说,卡方检验用于检查不同类别或类别之间的相关性和关联。
卡方检验的公式如下:
以下是使用 scikit-learn 的卡方的示例,由 Jason Brownlee,博士提供:
import pandas
import numpy
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
# load data
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = pandas.read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
# feature extraction
test = SelectKBest(score_func=chi2, k=4)
fit = test.fit(X, Y)
# summarize scores
numpy.set_printoptions(precision=3)
print(fit.scores_)
features = fit.transform(X)
# summarize selected features
print(features[0:5,:])
以下图表说明了前面的代码:
包装方法
包装方法是通过取子集和训练学习算法来执行的。根据训练的结果,我们可以选择我们模型的最佳特征。而且,你可能已经猜到,这些方法在计算上非常昂贵:
有许多包装技术,包括以下部分中列出的技术。
前向选择
前向选择使用搜索作为选择最佳特征的技术。这是一种迭代方法。在每次迭代中,我们添加更多特征以改进模型,直到我们没有进一步的改进为止:
向后消除
向后消除与前一种方法类似,但是这次我们从所有特征开始,并且在每次迭代中消除一些特征,直到模型停止改进:
递归特征消除
你可以看到递归特征消除作为一种贪婪的优化算法。这种技术是通过创建具有不同子集的模型并计算最佳执行特征来执行的,根据消除排名对它们进行评分。
这个脚本与前一个类似,但它使用递归特征消除作为特征选择方法:
from pandas import read_csv
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
# load data
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.data.csv"
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
dataframe = read_csv(url, names=names)
array = dataframe.values
X = array[:,0:8]
Y = array[:,8]
# feature extraction
model = LogisticRegression()
rfe = RFE(model, 3)
fit = rfe.fit(X, Y)
print("Num Features: %d") % fit.n_features_print("Selected Features: %s") % fit.support_
print("Feature Ranking: %s") % fit.ranking_
以下图表说明了前面的代码:
嵌入方法
特征选择嵌入方法的主要目标是学习哪些特征对机器学习模型的准确性贡献最大。它们具有内置的惩罚函数以减少过拟合:
一些嵌入技术列在以下部分。
Lasso 线性回归 L1
在统计学中,Lasso 是一种回归分析方法。Lasso 线性回归 L1 简单地增加了一个与系数大小的绝对值等价的惩罚。以下是 Python 和 sckit-learn 中该方法的实现:
>>> from sklearn.svm import LinearSVC
>>> from sklearn.datasets import load_iris
>>> from sklearn.feature_selection import SelectFromModel
>>> iris = load_iris()
>>> X, y = iris.data, iris.target
>>> X.shape
>>> lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
>>> model = SelectFromModel(lsvc, prefit=True)
>>> X_new = model.transform(X)
>>> X_new.shape
岭回归 L2
岭回归 L2 方法增加了一个与系数大小的平方等价的惩罚。换句话说,它执行 L2 正则化。
基于树的特征选择
基于树的特征选择方法用于检查和计算特征的重要性。以下是一个示例,展示了如何使用 scikit-learn 官方文档提供的基于树的特征选择技术:
>>> from sklearn.ensemble import ExtraTreesClassifier
>>> from sklearn.datasets import load_iris
>>> from sklearn.feature_selection import SelectFromModel
>>> iris = load_iris()
>>> X, y = iris.data, iris.target
>>> X.shape
>>> clf = ExtraTreesClassifier()
>>> clf = clf.fit(X, y)
>>> clf.feature_importances_
>>> model = SelectFromModel(clf, prefit=True)
>>> X_new = model.transform(X)
>>> X_new.shape
正如我之前所说,特征选择是在预处理阶段使用的,因此您可以使用 scikit-learn 来构建一个流水线,就像以下示例中的那样:
Classifier = Pipeline([
('feature_selection', SelectFromModel(<SelectionTechniqueHere>))),
('classification', <ClassificationAlgorithmHere>)
])
Classifier.fit(X, y)
一本名为An Introduction to Variable and Feature Selection的好书,作者是 Isabelle Guyon 和 Andre Elisseeff,其中包括了一个更好的特征选择清单。
要了解更多有关完整清单的信息,您可以浏览machinelearningmastery.com/an-introduction-to-feature-selection/。
机器学习的最佳实践
在之前的章节中,我们看到了如何进行特征工程来增强我们的机器学习系统的性能。现在,我们将讨论一些建立健壮智能系统的技巧和最佳实践。让我们探索机器学习项目不同方面的一些最佳实践。
信息安全数据集
数据是每个机器学习模型的重要组成部分。为了训练模型,我们需要提供数据集。在阅读之前的章节时,您可能已经注意到,要构建准确和高效的机器学习模型,您需要大量的数据,即使在清理数据之后也是如此。拥有大量可用数据的大公司使用其内部数据集来构建模型,但是像初创公司这样的小组织通常很难获取这么多的数据。国际规则和法规使这一任务变得更加困难,因为数据隐私是信息安全的重要方面。每个现代企业都必须保护其用户的数据。为了解决这个问题,许多机构和组织提供了公开可用的数据集,以便其他人可以下载并构建用于教育或商业用途的模型。一些信息安全数据集如下:
-
用于入侵检测的控制区域网络(CAN)数据集(OTIDS):
ocslab.hksecurity.net/Dataset/CAN-intrusion-dataset -
用于入侵检测的汽车黑客数据集:
ocslab.hksecurity.net/Datasets/CAN-intrusion-dataset -
用于网络犯罪分析的网络黑客数据集:
ocslab.hksecurity.net/Datasets/web-hacking-profiling -
基于 API 的恶意软件检测系统(APIMDS)数据集:
ocslab.hksecurity.net/apimds-dataset -
入侵检测评估数据集(CICIDS2017):
www.unb.ca/cic/datasets/ids-2017.html -
Tor-nonTor 数据集:
www.unb.ca/cic/datasets/tor.html -
Android 广告软件和一般恶意软件数据集:
www.unb.ca/cic/datasets/android-adware.html
Jupyter 项目
Jupyter Notebook 是一个开源的 Web 应用程序,用于创建和共享编码文档。我强烈推荐它,特别是对于新手数据科学家,原因有很多。它将使您能够直接编写和可视化输出。它非常适合发现和处理数据;探索数据是构建机器学习模型的重要步骤。
Jupyter 的官方网站是jupyter.org/:
要使用pip安装它,只需输入以下内容:
python -m pip install --upgrade pip
python -m pip install jupyter
使用 GPU 加速训练
正如你所知,即使进行了良好的特征工程,机器学习训练在计算上是昂贵的。训练学习算法的最快方法是使用图形处理单元(GPU)。一般来说,虽然不是所有情况,使用 GPU 是训练模型的明智决定。为了克服 CPU 性能瓶颈,最好使用聚集/分散 GPU 架构,执行并行操作以加快计算速度。
TensorFlow 支持使用 GPU 来训练机器学习模型。因此,设备被表示为字符串;以下是一个例子:
"/device:GPU:0" : Your device GPU
"/device:GPU:1" : 2nd GPU device on your Machine
要在 TensorFlow 中使用 GPU 设备,可以添加以下行:
with tf.device('/device:GPU:0'):
<What to Do Here>
你可以使用单个 GPU 或多个 GPU。不要忘记安装 CUDA 工具包,使用以下命令:
Wget "http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_8.0.44-1_amd64.deb"
sudo dpkg -i cuda-repo-ubuntu1604_8.0.44-1_amd64.deb
sudo apt-get update
sudo apt-get install cuda
按照以下方式安装 cuDNN:
sudo tar -xvf cudnn-8.0-linux-x64-v5.1.tgz -C /usr/local
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64"
export CUDA_HOME=/usr/local/cuda
选择模型和学习曲线
为了提高机器学习模型的性能,有许多超参数需要调整。使用的数据越多,出现的错误就越多。为了处理这些参数,有一种称为GridSearchCV的方法。它通过迭代在预定义的参数值上执行搜索。GridSearchCV默认使用score()函数。要在 scikit-learn 中使用它,可以使用以下行导入:
from sklearn.grid_search import GridSearchCV
学习曲线用于了解机器学习模型的性能。要在 scikit-learn 中使用学习曲线,可以将其导入到 Python 项目中,如下所示:
from sklearn.learning_curve import learning_curve
机器学习架构
在现实世界中,数据科学家并不认为数据像公开可用的数据集那样干净。现实世界的数据以不同的方式存储,数据本身也以不同的类别呈现。因此,机器学习从业者需要构建自己的系统和流程来实现他们的目标并训练模型。典型的机器学习项目遵循以下架构:
编码
良好的编码技能对于数据科学和机器学习非常重要。除了使用有效的线性代数、统计学和数学,数据科学家还应该学会如何正确编码。作为一名数据科学家,你可以选择许多编程语言,比如 Python、R、Java 等。
尊重编码的最佳实践非常有帮助,也强烈推荐。通过以下提示可以编写优雅、清晰和易懂的代码:
-
注释对于可理解的代码非常重要。因此,不要忘记一直对代码进行注释。
-
为变量、函数、方法、包和模块选择正确的名称。
-
每个缩进级别使用四个空格。
-
正确结构化你的存储库。
-
遵循常见的样式指南。
如果你使用 Python,你可以遵循这个伟大的格言,称为Python 之禅,由传奇人物 Tim Peters 撰写:
"美丽胜过丑陋。
显式胜于隐式。
简单胜于复杂。
复杂胜于复杂。
扁平胜于嵌套。
稀疏胜于密集。
可读性很重要。
特殊情况并不特别到足以打破规则。
尽管实用性胜过纯粹性。
错误不应该悄悄地传递。
除非明确地被压制。
面对模棱两可的情况,拒绝猜测的诱惑。
应该有一种——最好只有一种——明显的方法来做到这一点。
虽然这种方式一开始可能不太明显,除非你是荷兰人。
现在胜于永远。
虽然从来没有比现在更好。
如果实现难以解释,那就是一个坏主意。
如果实现容易解释,那可能是一个好主意。
命名空间是一个伟大的想法——让我们做更多这样的事情!
数据处理
良好的数据处理有助于成功构建机器学习项目。加载数据集后,请确保所有数据都已正确加载,并且读取过程正在正确执行。在对数据集执行任何操作后,请检查生成的数据集。
商业背景
智能系统与业务方面高度相关,毕竟您正在使用数据科学和机器学习来解决业务问题或构建商业产品,或者从获取的数据中获得有用的见解,以做出明智的决策。在构建机器学习模型时,识别正确的问题并提出正确的问题是重要的,以解决业务问题。
总结
这本书是一个实用指南,教你如何使用开源库、Python 和一套开源项目来构建机器学习项目,以抵御网络威胁和恶意活动。我们不止于此;我们还向您展示了如何使用对抗机器学习来攻击这些模型。通过这样做,您获得了一套分析数据、构建防御系统和突破下一代安全防护的技能。我们在书中讨论了许多观点,以帮助您构建更好的模型。
问题
-
特征工程和特征选择有什么区别?
-
主成分分析(PCA)和特征选择有什么区别?
-
我们如何对日期和小时等特征进行编码?
-
为什么打印出训练和测试准确性很有用?
-
我们如何部署机器学习模型并在产品中使用它?
-
为什么特征工程比其他步骤花费更多时间?
-
虚拟变量的作用是什么?
进一步阅读
论文和幻灯片:
-
特征工程 - 知识发现与数据挖掘 1,作者:Roman Kern:
kti.tugraz.at/staff/denis/courses/kddm1/featureengineering.pdf -
特征工程和选择(
people.eecs.berkeley.edu/~jordan/courses/294-fall09/lectures/feature/slides.pdf)- CS 294:实用机器学习,伯克利:people.eecs.berkeley.edu/~jordan/courses/294-fall09/lectures/feature/ -
特征工程 作者:Leon Bottou,普林斯顿:
www.cs.princeton.edu/courses/archive/spring10/cos424/slides/18-feat.pdf
博客文章:
-
发现特征工程-如何进行特征工程以及如何擅长它:
machinelearningmastery.com/discover-feature-engineering-how-to-engineer-features-and-how-to-get-good-at-it/
书籍:
-
特征提取、构造和选择:数据挖掘视角:
www.amazon.com/dp/0792381963?tag=inspiredalgor-20 -
特征提取:基础和应用:
www.amazon.com/dp/3540354875?tag=inspiredalgor-20 -
计算机视觉的特征提取和图像处理,第三版:
www.amazon.com/dp/0123965497?tag=inspiredalgor-20
第十一章:评估
第一章:- 机器学习入门
- 尽管机器学习是一个有趣的概念,但在有用的有限业务应用中。
假
- 机器学习应用程序太复杂,无法在云中运行。
假
- 对于两次 k 均值聚类运行,预期得到相同的聚类
结果?
不
- 具有离散值目标属性的预测模型可以称为:
分类模型
- 以下哪种技术执行与退出类似的操作
神经网络?
装袋
- 神经网络的哪种架构最适合解决图像识别问题?
卷积神经网络
- 深度学习与传统机器学习有何不同?
深度学习算法可以处理更多数据,并且在较少的数据科学家监督下运行。
- 以下哪种技术在机器学习项目中经常使用?
以上所有
第二章:- 钓鱼域名检测
- 以下是一些文本清理任务:
-
清除文本中的停用词、数字和标点符号。
-
执行词形还原。
-
创建一个包括它们频率的单词字典。
-
从字典中删除非单词。
-
从数据中提取特征。
查看Chapter2-Practice文件夹以获取答案:github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter%202/Chaptre2-Practice。
- 准备特征向量及其标签。
train_labels = np.zeros(702)
train_labels[351:701] = 1
train_matrix = extract_features(train_dir)
- 使用线性支持向量机分类器训练模型。
model = LinearSVC()
model.fit(train_matrix,train_labels)
- 打印模型的混淆矩阵。
result = model.predict(test_matrix)
print (confusion_matrix(test_labels,result))
第三章:- 使用 API 调用和 PE 标头检测恶意软件
- 使用 pandas python 库加载数据集,这次添加
low_memory=False参数。搜索该参数的作用。
df = pd.read_csv(file_name, low_memory=False)
- 准备用于训练的数据。
original_headers = list(df.columns.values)
total_data = df[original_headers[:-1]]
total_data = total_data.as_matrix()
target_strings = df[original_headers[-1]]
- 使用
test_size=0.33参数拆分数据。
train, test, target_train, target_test = train_test_split(total_data, target_strings, test_size=0.33, random_state=int(time.time()))
- 创建一个包含
DecisionTreeClassifier()、RandomForestClassifier(n_estimators=100)和AdaBoostClassifier()的分类器集合:
classifiers = [
RandomForestClassifier(n_estimators=100),
DecisionTreeClassifier(),
AdaBoostClassifier()]
- 什么是
AdaBoostClassifier()?
AdaBoost 分类器是一个元估计器,它首先在原始数据集上拟合一个分类器,然后在相同数据集上拟合额外的分类器副本。
- 使用三个分类器训练模型,并打印每个分类器的指标。
请查看Chapter3-Practice文件夹以获取解决方案:github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter%203/Chapter3-Practice.
第四章:- 使用深度学习检测恶意软件
- MLP 网络和深度学习网络之间有什么区别?
深度网络已经是多层感知器网络,但至少有三个隐藏层。
- 为什么最近 DL 开始起飞?
因为我们可以访问更多的计算能力和数据。
- 为什么我们需要通过不同模型进行多次迭代?
因为没有人可以在没有迭代的情况下总是找到最佳模型或超参数。
- 需要哪种类型的深度学习来将英语翻译成法语?
循环神经网络(RNN)
- 为什么恶意软件可视化是分类恶意软件的好方法?
因为我们可以使用最先进的图像识别来构建恶意软件分类器。
- 激活函数的作用是什么?
它定义了给定节点的输出。换句话说,它将 A-NN 的节点的输入信号转换为输出信号。
- 你能提到三种 DL 架构吗?
-
卷积神经网络(CNNs)
-
循环神经网络(RNNs)
-
长/短期记忆网络(LSTMs)
第五章:- 机器学习中的僵尸网络检测
与每章结束后一样,我们将给您机会练习所学内容并评估您的技能。本章的 GitHub 存储库包含练习文件夹中的僵尸网络流量数据集的链接:github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter5:
-
下载数据集,并使用 pandas 库加载它
-
选择合适的特征
-
识别训练和测试集,然后将它们导出到
.pickle文件中 -
加载
.pickle文件 -
使用第五章的相同代码块,使用机器学习进行僵尸网络检测。
导入支持向量机分类器:
from sklearn.svm import *
训练 SVM 模型:
clf= SVC(kernel='rbf')
clf.fit(Xdata, Ydata)
打印出构建模型的准确性:
Score = clf.score(XdataT,YdataT)
print (“The Score of the SVM Classifier is”, Score * 100)
第六章:- 异常检测系统中的机器学习
- 什么是异常?
异常是指偏离标准、正常或预期的事物。
- 什么是马尔可夫链?
马尔可夫链,或者我们所说的马尔可夫过程,是用于任何根据固定概率改变其状态的随机系统的随机模型。
- 隐马尔可夫模型是什么?
隐藏马尔可夫模型是一个马尔可夫过程,我们无法直接观察系统的状态。每个状态都有一个固定的发射概率。HMM 模型或分类器的主要目标是为一系列序列分配标签,这意味着将一系列观察链接到一系列标签。
- 我们如何使用隐藏马尔可夫模型检测异常?
根据隐藏马尔可夫模型的定义,我们可以使用它来区分网络流量的正常行为和异常行为。
- 时间序列异常检测和其他类型的异常检测有什么区别?
时间序列是在连续时间获得的值,通常它们之间的间隔是相等的。在时间序列异常检测中,我们正在检测在特定时间记录的数据点序列中的异常。在大多数其他检测方法中,我们使用诸如基于图的技术。
- 监督和无监督机器学习异常检测有什么区别?
这两种模型的区别在于所使用的机器学习算法。例如,在监督机器学习异常检测中,我们可以使用分类;而在无监督机器学习异常检测中,我们可以使用聚类。
第七章:- 检测高级持续威胁
- 以下哪个不是网络攻击的钻石模型中的步骤?
(a) 扫描
- 以下哪个选项不是入侵的钻石模型的节点?
分析?
(c) 程序
- Logstash 配置文件需要多少部分?
(b) 3
- 在 ElasticSearch 中,什么是索引?
(a) 将数据存储在索引中的过程
- 在 Elasticsearch 中,什么是节点?
(a) Elasticsearch 的一个实例
- 在 Elasticsearch 中,什么是分片?
(c) 共享资源(RAM,vCPU)
- Elasticsearch 有模式吗?
(a) 是的
第八章:- 使用对抗机器学习规避入侵检测系统
- 您能简要解释一下为什么过度训练机器学习模型不是一个好主意吗?
好主意?
通过过度训练机器学习模型,我们过度训练模型,使其在新数据上的性能受到负面影响。这也被称为过拟合。
- 过拟合和欠拟合有什么区别?
过拟合是指过度训练模型,而欠拟合是指模型既不能对训练数据建模,也不能推广到新数据。
- 规避和毒化攻击有什么区别?
在规避对抗攻击中,攻击者尝试许多不同的样本来识别绕过学习模式;而在毒化攻击中,攻击者在训练阶段中毒化模型。
- 对抗聚类是如何工作的?
当攻击者操纵输入数据(添加小部分攻击样本)时,对抗性聚类发生,以便新添加的样本可以隐藏在现有的聚类中。
- 用于避免入侵检测系统的对抗攻击类型是什么?
演示中使用的攻击称为基于雅可比显著性图的攻击。
- 前述攻击是规避还是毒化攻击?
这是一种毒化对抗攻击。
第九章:- 绕过机器学习恶意软件检测器
- 生成对抗网络的组件是什么?
生成对抗网络的两个主要组件是生成器和鉴别器。
- 生成器和鉴别器之间有什么区别?
生成器以潜在样本作为输入。它们是随机生成的数字,并且经过训练以生成图像,而鉴别器只是一个使用监督学习技术训练的分类器,用于检查图像是真实的(1)还是伪造的(0)。
- 我们如何确保恶意软件对抗样本在…时仍然有效?
我们正在生成它们吗?
为了避免无效样本,我们可以使用沙盒/Oracle。
- 进行一些研究,然后简要解释如何检测对抗样本
要检测对抗样本,我们可以使用二值阈值处理来去除噪音。
- 强化学习与深度学习有何不同?
强化学习通过探索从某些状态可用的动作来学习如何最大化奖励函数,而深度学习则是从它所展示的示例中学习。
- 监督学习和强化学习之间有什么区别?
在监督学习中,给定输入数据 X 和标签 Y,我们正在学习一个将 X 映射到 Y 的函数 f:X→Y。在强化学习中,代理在经历了一定数量的经验后变得更加智能。
- 在强化学习中,代理如何学习?
在强化学习中,代理通过与基于奖励函数的环境交互来学习,以优化其性能。
第十章:- 机器学习和特征工程的最佳实践
- 特征工程和特征选择之间有什么区别?
特征选择是特征工程的一部分。
- 主成分分析(PCA)和特征选择之间有什么区别?
特征选择获取数据集并为我们提供最佳的特征集,而主成分分析是一种降维方法。
- 我们如何对日期和小时等特征进行编码?
其中一种技术是添加时间变量的(正弦,余弦)变换。
- 为什么打印出训练和测试准确度很有用?
通过比较这两个指标来检测过拟合是很有用的。
- 我们如何部署机器学习模型并在产品中使用它?
有许多将机器学习模型投入生产的方法,例如基于您的模型(在线、离线?深度学习、支持向量机、朴素贝叶斯?)的网络服务和容器化。
- 为什么特征工程比其他步骤花费更多时间?
因为分析、清理和处理特征比构建模型需要更多时间。
- 虚拟变量的作用是什么?
虚拟变量是在回归分析中使用的数值变量,用于表示研究中样本的子组。在研究设计中,虚拟变量通常用于区分不同的处理组。