原文:
annas-archive.org/md5/74E92091FA78BD2C9635BCA05C8FE700
译者:飞龙
第五章:机器学习下的僵尸网络检测
如今,连接设备在现代生活中扮演着重要角色。从智能家居电器、计算机、咖啡机和摄像头,到连接的汽车,我们生活方式的巨大转变使我们的生活变得更加轻松。不幸的是,这些暴露的设备可能会受到攻击,并且攻击者和网络犯罪分子可能会稍后使用它们来实施更大规模的攻击。安全供应商提供了许多解决方案和产品来防御僵尸网络,但在本章中,就像我们在之前的章节中所做的那样,我们将学习如何使用 Python 和机器学习技术构建新颖的僵尸网络检测系统。
在本章中,我们将看到:
-
僵尸网络概述
-
如何使用不同的机器学习算法构建僵尸网络检测器
-
如何构建 Twitter 僵尸网络检测器
技术要求
您将在以下存储库中找到所有讨论的代码,以及其他一些有用的脚本:github.com/PacktPublishing/Mastering-Machine-Learning-for-Penetration-Testing/tree/master/Chapter5
。
僵尸网络概述
僵尸网络是bot和net两个术语的组合。bot 部分表示这种恶意软件自动化事物和任务,就像机器人一样。第二部分指的是网络,换句话说,是一组受损设备的网络。因此,根据定义,僵尸网络是一种恶意软件,它攻击互联网上的计算机,并通过命令和控制服务器控制它们执行各种自动化任务,包括发送垃圾邮件和执行分布式拒绝服务(DDoS)攻击。受攻击的机器加入了一个庞大的受损机器网络。以前几年最引人注目的僵尸网络之一是Mirai 僵尸网络。Mirai 在日语中意为未来。这个僵尸网络攻击了数百万在线设备,特别是物联网(IoT)设备,通过扫描和识别易受攻击的机器,利用大多数设备使用默认登录凭据的事实。僵尸网络执行的一些任务包括:
-
广告欺诈和发送垃圾邮件
-
加密货币挖矿
-
窃取个人数据和敏感信息
-
执行 DDoS 攻击
-
执行暴力攻击
以下图表描述了僵尸网络生态系统的不同参与者:
黑客是一项有方法的任务。罪犯和网络攻击者通常使用相同的定义步骤。作为渗透测试人员和信息安全专业人员,您了解黑客阶段,即信息收集,或者我们所说的侦察;扫描;获取访问权限;保持访问权限;最后清除痕迹。因此,僵尸网络通常遵循一些定义的步骤。僵尸网络基于四个不同的阶段工作:
-
感染:在这个阶段,攻击者通过发送恶意软件感染目标机器。
-
连接:在这个阶段,僵尸网络与控制和命令服务器建立互联网连接,以接收命令和自动任务。
-
控制:在这个阶段,攻击发生,例如发送垃圾邮件。
-
繁殖:在这个阶段,僵尸网络将尝试感染更多的机器加入网络,并成为我们所说的僵尸:
使用多种机器学习技术构建僵尸网络检测器模型
在本节中,我们将学习如何使用许多机器学习算法构建不同的僵尸网络检测系统。作为第一个实验室的开始,让我们通过使用不同的分类器构建基于机器学习的僵尸网络检测器。到目前为止,我希望您已经清楚地了解了构建机器学习系统的主要步骤。因此,我相信您已经知道,作为第一步,我们需要寻找一个数据集。许多教育机构和组织都提供了从内部实验室收集的数据集。最知名的僵尸网络数据集之一称为CTU-13数据集。这是捷克共和国 CTU 大学提供的带有僵尸网络、正常和背景流量的标记数据集。在他们的工作中,他们试图捕获真实的僵尸网络流量与正常流量和背景流量混合在一起。要下载数据集并查看更多信息,您可以访问以下链接:mcfp.weebly.com/the-ctu-13-dataset-a-labeled-dataset-with-botnet-normal-and-background-traffic.html
。
数据集是双向 NetFlow 文件。但是什么是双向 NetFlow 文件?Netflow 是由思科开发的互联网协议。该协议的目标是收集 IP 流量信息并监视网络流量,以便更清晰地了解网络流量流动。NetFlow 架构的主要组件是NetFlow Exporter、Netflow 收集器和流存储。以下图示了 NetFlow 基础设施的不同组件:
就 NetFlow 而言,当主机 A 向主机 B发送信息,然后从主机 B回复给主机 A时,该操作被称为单向 NetFlow。发送和回复被视为不同的操作。在双向 NetFlow 中,我们将来自主机 A和主机 B的流视为一个流。通过以下命令下载数据集:
$ wget --no-check-certificate https://mcfp.felk.cvut.cz/publicDatasets/CTU-13-Dataset/CTU-13-Dataset.tar.bz2
通过以下命令提取下载的tar.bz2
文件:
# tar xvjf CTU-13-Dataset.tar.bz2
该文件包含所有数据集,具有不同的场景。为了演示,我们将使用数据集 8(场景 8)。您可以选择任何场景,也可以使用自己收集的数据,或者其他机构提供的任何其他.binetflow
文件:
使用 pandas 通常加载数据:
>>> import pandas as pd
>>> data = pd.read_csv("capture20110816-3.binetflow")
>>> data['Label'] = data.Label.str.contains("Botnet")
在任何数据中心项目中,探索数据是至关重要的。例如,您可以从检查特征或列的名称开始:
>> data.columns
该命令会显示数据集的列:StartTime
、Dur
、Proto
、SrcAddr
、Sport
、Dir
、DstAddr
、Dport
、State
、sTos
、dTos
、TotPkts
、TotBytes
、SrcBytes
和Label
。这些列代表数据集中使用的特征;例如,Dur
代表持续时间,Sport
代表源端口,依此类推。您可以在本章的 GitHub 存储库中找到特征的完整列表。
在训练模型之前,我们需要构建一些脚本来准备数据。这一次,我们将构建一个单独的 Python 脚本来准备数据,稍后我们可以将其导入到主脚本中。
我将称第一个脚本为DataPreparation.py
。有许多提案可以帮助提取特征并准备数据以构建使用机器学习的僵尸网络检测器。在我们的案例中,我根据NagabhushanS构建的数据加载脚本定制了两个新脚本:
from __future__ import division
import os, sys
import threading
在导入所需的 Python 包后,我们创建了一个名为Prepare
的类来选择训练和测试数据:
class Prepare(threading.Thread):
def __init__(self, X, Y, XT, YT, accLabel=None):
threading.Thread.__init__(self)
self.X = X
self.Y = Y
self.XT=XT
self.YT=YT
self.accLabel= accLabel
def run(self):
X = np.zeros(self.X.shape)
Y = np.zeros(self.Y.shape)
XT = np.zeros(self.XT.shape)
YT = np.zeros(self.YT.shape)
np.copyto(X, self.X)
np.copyto(Y, self.Y)
np.copyto(XT, self.XT)
np.copyto(YT, self.YT)
for i in range(9):
X[:, i] = (X[:, i] - X[:, i].mean()) / (X[:, i].std())
for i in range(9):
XT[:, i] = (XT[:, i] - XT[:, i].mean()) / (XT[:, i].std())
第二个脚本称为LoadData.py
。您可以在 GitHub 上找到它,并直接在您的项目中使用它来从.binetflow
文件中加载数据并生成一个pickle
文件。
让我们使用之前开发的内容来训练模型。构建数据加载器并准备我们将要使用的机器学习算法后,是时候训练和测试模型了。
首先,从pickle
文件中加载数据,这就是为什么我们需要导入pickle
Python 库。不要忘记使用以下代码导入之前的脚本:
import LoadData
import DataPreparation
import pickle
file = open('flowdata.pickle', 'rb')
data = pickle.load(file)
选择数据部分:
Xdata = data[0]
Ydata = data[1]
XdataT = data[2]
YdataT = data[3]
作为机器学习分类器,我们将尝试许多不同的算法,以便稍后可以选择最适合我们模型的算法。导入所需的模块以使用sklearn
中的四种机器学习算法:
from sklearn.linear_model import *
from sklearn.tree import *
from sklearn.naive_bayes import *
from sklearn.neighbors import *
通过使用之前的模块构建数据。不要忘记通过输入import DataPreparation
来导入DataPreparation
:
>>> DataPreparation.Prepare(Xdata,Ydata,XdataT,YdataT)
现在,我们可以训练模型了;为此,我们将使用不同的技术来训练模型,以便稍后可以选择最合适的机器学习技术用于我们的项目。步骤与我们在以前的项目中学到的一样:在准备数据并选择特征之后,定义机器学习算法,拟合模型,并在定义其变量后打印出得分。
作为机器学习分类器,我们将测试其中许多。让我们从决策树开始:
- 决策树模型:
>>> clf = DecisionTreeClassifier()
>>> clf.fit(Xdata,Ydata)
>>> Prediction = clf.predict(XdataT)
>>> Score = clf.score(XdataT,YdataT)
>>> print (“The Score of the Decision Tree Classifier is”, Score * 100)
决策树分类器的得分为 99%
- 逻辑回归模型:
>>> clf = LogisticRegression(C=10000)
>>> clf.fit(Xdata,Ydata)
>>> Prediction = clf.predict(XdataT) >>> Score = clf.score(XdataT,YdataT)
>>> print ("The Score of the Logistic Regression Classifier is", Score * 100)
逻辑回归分类器的得分为 96%
- 高斯朴素贝叶斯模型:
>>> clf = GaussianNB()
>>> clf.fit(Xdata,Ydata)
>>> Prediction = clf.predict(XdataT)
>>> Score = clf.score(XdataT,YdataT)
>>> print("The Score of the Gaussian Naive Bayes classifier is", Score * 100)
高斯朴素贝叶斯分类器的得分为 72%
- k-最近邻模型:
>>> clf = KNeighborsClassifier()
>>> clf.fit(Xdata,Ydata)
>>> Prediction = clf.predict(XdataT)
>>> Score = clf.score(XdataT,YdataT)
>>> print("The Score of the K-Nearest Neighbours classifier is", Score * 100)
k-最近邻分类器的得分为 96%
- 神经网络模型:
要构建神经网络模型,请使用以下代码:
>>> from keras.models import *
>>> from keras.layers import Dense, Activation
>>> from keras.optimizers import *
model = Sequential()
model.add(Dense(10, input_dim=9, activation="sigmoid")) model.add(Dense(10, activation='sigmoid'))
model.add(Dense(1))
sgd = SGD(lr=0.01, decay=0.000001, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='mse')
model.fit(Xdata, Ydata, nb_epoch=200, batch_size=100)
Score = model.evaluate(XdataT, YdataT, verbose=0)
Print(“The Score of the Neural Network is”, Score * 100 )
使用这段代码,我们导入了所需的 Keras 模块,构建了层,用 SGD 优化器编译了模型,拟合了模型,并打印出了模型的得分。
如何构建 Twitter 机器人检测器
在之前的部分中,我们看到了如何构建基于机器学习的僵尸网络检测器。在这个新项目中,我们将处理一个不同的问题,而不是防御僵尸网络恶意软件。我们将检测 Twitter 机器人,因为它们也是危险的,可以执行恶意操作。对于模型,我们将使用NYU Tandon Spring 2017 Machine Learning Competition: Twitter Bot classification数据集。你可以从这个链接下载它:www.kaggle.com/c/twitter-bot-classification/data
。导入所需的 Python 包:
>>> import pandas as pd
>>> import numpy as np
>>> import seaborn
让我们使用 pandas 加载数据并突出显示机器人和非机器人数据:
>>> data = pd.read_csv('training_data_2_csv_UTF.csv')
>>> Bots = data[data.bot==1]
>> NonBots = data[data.bot==0]
使用 seaborn 进行可视化
在每个项目中,我都想帮助你发现新的数据可视化 Python 库,因为正如你所看到的,数据工程和可视化对于每个现代数据中心项目都是至关重要的。这一次,我选择了 seaborn 来可视化数据并在开始训练阶段之前探索数据。Seaborn 是一个用于制作统计可视化的 Python 库。以下是使用 seaborn 生成图表的示例:
>>> data = np.random.multivariate_normal([0, 0], [[5, 2], [2, 2]], size=2000)
>>> data = pd.DataFrame(data, columns=['x', 'y'])
>>> for col in 'xy':
... seaborn.kdeplot(data[col], shade=True)
例如,在我们的情况下,如果我们想要识别缺失的数据:
matplotlib.pyplot.figure(figsize=(10,6))
seaborn.heatmap(data.isnull(), yticklabels=False, cbar=False, cmap='viridis')
matplotlib.pyplot.tight_layout()
前两个代码片段是一些学习如何可视化数据的示例。可视化帮助数据科学家探索并了解更多关于数据的信息。现在,让我们回去继续构建我们的模型。
通过选择一些 Twitter 机器人使用的坏词来识别词袋。以下是机器人使用的坏词的示例。当然,你可以添加更多的词:
bag_of_words_bot = r'bot|b0t|cannabis|tweet me|mishear|follow me|updates every|gorilla|yes_ofc|forget' \
r'expos|kill|bbb|truthe|fake|anony|free|virus|funky|RNA|jargon' \ r'nerd|swag|jack|chick|prison|paper|pokem|xx|freak|ffd|dunia|clone|genie|bbb' \ r'ffd|onlyman|emoji|joke|troll|droop|free|every|wow|cheese|yeah|bio|magic|wizard|face'
- 现在,是时候识别训练特征了:
data['screen_name_binary'] = data.screen_name.str.contains(bag_of_words_bot, case=False, na=False)
data['name_binary'] = data.name.str.contains(bag_of_words_bot, case=False, na=False)
data['description_binary'] = data.description.str.contains(bag_of_words_bot, case=False, na=False)
data['status_binary'] = data.status.str.contains(bag_of_words_bot, case=False, na=False)
- 特征提取:让我们选择在我们的模型中使用的
features
:
data['listed_count_binary'] = (data.listed_count>20000)==False
features = ['screen_name_binary', 'name_binary', 'description_binary', 'status_binary', 'verified', 'followers_count', 'friends_count', 'statuses_count', 'listed_count_binary', 'bot']
- 现在,用决策树分类器训练模型:
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, roc_curve, auc
from sklearn.model_selection import train_test_split
- 我们导入一些先前讨论过的模块:
X = data[features].iloc[:,:-1]
y = data[features].iloc[:,-1]
- 我们定义分类器:
clf = DecisionTreeClassifier(criterion='entropy', min_samples_leaf=50, min_samples_split=10)
- 我们分割分类器:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=101)
- 我们拟合模型:
clf.fit(X_train, y_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
- 我们打印出准确率分数:
print("Training Accuracy: %.5f" %accuracy_score(y_train, y_pred_train))
print("Test Accuracy: %.5f" %accuracy_score(y_test, y_pred_test))
我们的模型以 88%的检测率检测到了 Twitter 机器人,这是一个很高的准确率。
这种技术并非检测僵尸网络的唯一可能方式。研究人员提出了许多基于不同机器学习算法的其他模型,例如线性 SVM 和决策树。所有这些技术的准确率都达到了 90%。大多数研究表明,特征工程是改进机器学习模型的关键因素。
要研究一个真实案例,可以查看一篇名为从学习中学到的东西 - 了解机器学习在僵尸网络攻击中的能力和局限性的论文(arxiv.org/pdf/1805.01333.pdf
),作者是 David Santana,Shan Suthaharan 和 Somya Mohanty。
总结
本章是一个轻量级指南,介绍了有关僵尸网络基础知识以及如何使用不同技术构建基于机器学习的检测器。此外,我们还讨论了如何识别 Twitter 机器人。下一章将深入探讨异常情况以及如何使用新方法构建多个项目来识别异常情况。
问题
在每章结束后,我们都会给你机会练习所学的知识并评估你的技能。本章的 GitHub 存储库中包含了Practice
文件夹中的一个僵尸网络流量数据集的链接:
-
下载数据集并使用 pandas 库加载它
-
选择合适的特征
-
识别训练集和测试集,然后将它们导出到一个 pickle 文件中
-
加载 pickle 文件
-
导入支持向量机分类器并拟合模型
-
训练 SVM 模型
-
打印出构建的模型的准确率
进一步阅读
要了解更多关于僵尸网络以及如何使用机器学习检测它们的知识,我强烈建议你查看这些有用的外部链接:
-
僵尸网络如何扩展以及如何保护自己免受它们的侵害:
bitninja.io/blog/2016/01/11/how-botnets-expand-and-how-protect-against-them
-
僵尸网络基础知识 - 不要成为僵尸!:
blog.trendmicro.com/botnet-basics/
-
用于僵尸网络检测的深度神经网络:
arxiv.org/abs/1802.04289
-
使用深度自动编码器进行物联网僵尸网络攻击的基于网络的检测(N-BaIoT):
arxiv.org/abs/1805.03409
-
用于传感器网络入侵检测的混合谱聚类和深度神经网络集成算法 (
www.covert.io/research-papers/deep-learning-security/A%20Hybrid%20Spectral%20Clustering%20and%20Deep%20Neural%20Network%20Ensemble%20Algorithm%20for%20Intrusion%20Detection%20in%20Sensor%20Networks.pdf
) -
用于僵尸网络检测行为的循环神经网络分析 (
www.covert.io/research-papers/deep-learning-security/An%20Analysis%20of%20Recurrent%20Neural%20Networks%20for%20Botnet%20Detection%20Behavior.pdf
)
第六章:异常检测系统中的机器学习
对于任何企业来说,网络上的未经授权活动可能是一场噩梦。保护客户数据是最重要的问题,也是每个企业所有者的责任。部署入侵检测系统是现代组织可以采取的明智决定,以防御恶意入侵。不幸的是,攻击者和黑客总是在想出新的技术来绕过保护,以获取对网络的未经授权访问。这就是为什么机器学习技术是保护网络免受甚至复杂和攻击的良好解决方案。
本章将是发现网络异常并学习如何从头开始构建入侵检测系统的一站式指南,使用公开可用的数据集和尖端的开源 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