4 AI检测序列事件中的异常事件

4.1 安全问题

异常检测在各行各业被广泛考虑,以实现更高级别的安全性。异常检测寻找观察行为中的意外变化(即与正常情况的偏离)。当应用于入侵检测系统(IDS)时,如果识别到离群值,它会怀疑并预测攻击。

假设在特定时间间隔内监控网络活动,我们使用eᵢ表示第i个活动。让我们用E = {e₁, e₂, e₃, ..., eₙ}表示长时间内所有网络活动的集合。异常检测器将eᵢ视为一个事件,将{eᵢ, eᵢ₊₁, ..., eᵢ₊ⱼ}视为事件序列。

通常,异常检测有两个基本假设:a)在正常行为中,异常事件子序列很少存在;b)它们的特征与正常事件显著不同。因此,安全分析人员对数据集E进行异常检测,以识别与所有其他时间间隔相比异常的时间间隔(事件子序列)。

4.2 数据集

我们介绍两个数据集,分别是UNSW-NB15 [56] 和 SOSP2009 [87]。

4.2.1 UNSW-NB15数据集

澳大利亚网络安全中心(ACCS)的网络安全实验室于2015年发布了UNSW-NB15。该数据集包括真实正常活动和由IXIA PerfectStorm工具生成的合成网络攻击行为的混合。

首先,需要注意流是从源IP到目的地的数据包序列。数据集包含2,218,761个(87.35%)良性流和321,283个(12.65%)攻击流,总计2,540,044个流。具体而言,数据集包括九种类型的攻击,分别是Fuzzers、Analysis、Backdoors、DoS、Exploits、Generic、Reconnaissance、Shellcode和Worms,这些攻击是由Tcpdump工具捕获的。数据集中的数据包由Argus数据包处理器、Bro和其他十二个附加算法提供的49个不同特征进行描述。

最常用的训练集(UNSW_NB15_training-set.csv1),包含175,341个流,以及测试集(UNSW_NB15_testing-set.csv2),包含82,332个流,是整个数据集的一部分,并可供研究人员使用,以帮助他们开发基于数据的攻击检测技术。

4.2.2 SOSP 2009 Log数据集

表4.2提供了SOSP 2009日志数据集的简要概述,实际上是一个Hadoop文件系统(HDFS)控制台日志数据集。此日志集在私有云环境中使用基准工作负载生成。通过手工制定的规则,日志条目被手动标记以识别异常。具体而言,日志数据集包含来自在203个Amazon EC2节点上运行的Hadoop MapReduce操作的1100多万个日志条目,历时两天。每个日志条目都有一个块标识符(表示为块ID),每个HDFS块可以被视为一个独立的线程。

每个日志条目对应于一个独特的事件。所有事件都被分类为一组类别:每个类别由一个日志键ki表示。此外,每个会话被定义为发生在特定块ID上的一系列事件。(没有会话涉及两个或更多块ID。)由于没有块ID出现在两个或更多会话中,我们可以直接将块ID标记为正常或异常。如表4.2所示,标签(即正常或异常)是在会话级别提供的,有558,223个正常会话和16,838个异常会话。整个数据集包括一个正常训练集(4,855个解析的会话),一个正常测试集(553,366个解析的会话),一个异常训练集(1,638个解析的会话)和一个异常测试集(15,200个解析的会话)。

4.3 数据处理

4.3.1 SOSP 2009 Log数据集

代码4.1是一个原始HDFS日志的示例,记录了“INFO”文本后的系统行为、源IP地址和目标IP地址。“blk_-1608999687919862906”是一个块ID。表4.3展示了一些正常的块ID和一些异常的块ID。

在数据处理阶段,我们首先将日志键重新设计为三个键集K0(新基础)、K1和K2。它们分别包含31、101和304个日志键。由于会话和块ID都有标签,因此可以安全地使用日志键对每个事件(即日志条目)进行编码,而无需修改原始事件序列。在配置seqlen = 10下,每个键集的统计信息如表4.4所示。这些键集来自同一个日志,只是K1和K2通过重新附加附加字符串来丢弃较少的信息,例如:

有三种附加字符串类型:

  1. 对于涉及文件路径的两个日志键,我们附加32个文件路径附加字符串之一(例如/user/root/randtxt/temporary/task*/part*)。

  2. 对于涉及文件大小的两个日志键,我们附加七个10 MB间隔附加字符串之一(例如0-10 MB)。

  3. 对于涉及IP地址的事件,我们根据以下规则附加附加字符串:

    • 如果日志条目涉及源IP地址和目标IP地址,我们检查并附加表示它是否“在本地”内的附加字符串;如果不是,则通过IP前缀(例如10.251.7*)检查它是否“在子网内”或“在子网之间”。

    • 如果日志条目涉及源IP地址或目标IP地址之一,我们附加表示方向和IP前缀的附加字符串(例如,从10.251.7*)。

对于K1和K2,IP前缀的粒度不同:对于K1,它使用前两个小数(例如10.251.),而对于K2,它使用一个更多的小数(例如10.251.7)。我们通过附加附加字符串来拆分K0,但我们还丢弃了没有发生的键。

代码4.2展示了数据处理的代码片段。

4.3.2 UNSW-NB15数据集

首先,表4.5展示了UNSW-NB15数据集中的一些原始数据样本。

数据处理的代码片段如代码4.3所示。它提取源IP、源端口、目标IP和目标端口,然后将它们合并为一个载入序列的事件。更重要的是,标签和日志键是不可避免的。对于日志键,一些具有“-”和“空格”值的出现被移除。包含数字值的一些文本类型被转换为数字类型。特征列的中位数用于替换空值。最后,我们附加一些附加键,将其制作成一个日志键序列(更多细节见“data/unswnb15/key.py”)。

4.4 模型架构

此用例在离散事件或日志上应用异常检测。受自然语言处理(NLP)启发,研究人员最近已经将相关的NLP方法调整为离散日志的异常检测,将离散事件视为单词,将日志视为句子[47, 48]。因此,一种常用的检测策略是:首先,让模型预测即将发生的日志事件;其次,如果预测的事件与观察到的事件(在实际系统中)明显不同,就对观察到的事件发出入侵警报。

然而,[93]中观察到这种策略可能无法充分利用序列的独特特征,因为一个操作受到的影响不仅来自先前的操作,还来自后续事件。因此,此用例将利用[93]中提出的双向LSTM模型,以帮助安全分析人员在异常检测中实现更高的准确性。

简而言之,双向LSTM模型包括四个主要组件(见图4.1):嵌入层、深度LSTM自编码器、事件分类器和异常评论家。嵌入层E将事件序列S嵌入嵌入分布X;自编码器分析(编码)X并重构(解码)分类逻辑分布Y;事件分类器将Y转换为分类概率分布P;评论家将P与S进行比较并报告S是正常的还是异常的。

4.4.1 双向LSTM网络架构

与LSTM不同,双向LSTM包含前向和后向层,它们连接到相同的输出层。随后,来自一个LSTM的每个输出的连接构成了Bi-LSTM,连接的向量将传递到下一个LSTM层。最后,最后一个线性层将具有激活函数,例如softmax函数。Bi-LSTM的架构如图4.2所示。

4.4.2 嵌入层

由于我们将离散事件序列S = [et | 1 ≤ t ≤ T] 作为输入,我们需要将 et ∈ K 嵌入到模型能够识别的嵌入向量中,其中 K = {ki | 1 ≤ k ≤ V } 是词汇大小为 V = |K| 的离散事件键的集合。除了离散日志键 K,我们还添加了三个特殊的填充键:序列开始、序列结束和未知(如代码4.4所示,由文件“models/util.py”中的Codebook类实现)。一方面,序列开始和序列结束提供了额外的特征,以帮助自编码器和预测器。另一方面,未知键用于提高计算性能。

我们训练了一个额外的嵌入层,与其他层一起进行训练,而不是利用其他现有的嵌入方法生成词嵌入向量,因为通过这种方式可以定制嵌入函数(如代码4.5所示,由文件“models/dablog.py”中的Dablog类实现)。

4.4.3 深度LSTM自编码器

与普通的深度自编码器不同,普通深度自编码器学习正常数据的恒等函数并重建正常数据分布,而[37]提出的深度LSTM自编码器试图从嵌入层中重构分类事件的logit输入。为了解决时间敏感的事件,这个自编码器的目标函数也遵循典型的深度自编码器。我们设X为输入分布,ψ ◦ ϕ(X)为目标分布,因此损失函数可以写为:

其中,ϕ是编码器函数,ψ是解码器函数,E是将S映射到X的嵌入函数,rev是一个反转分布矩阵的函数。

我们使用rev函数的原因是Y与Xe的顺序相反,这是由于LSTM的隐藏状态。如图4.3所示,我们可以通过以下方式简单表示LSTM网络:

其中,ht是时间步t处的隐藏状态,xt是当前数据点。正如我们所看到的,LSTM从第1步到最后一个时间步迭代计算这个函数。类似于函数堆栈,我们可以将这个编码器过程看作是将xt推入堆栈hT,解码器过程是从堆栈hT中弹出xt。因此,Xe和Y的顺序是相反的。 这个自编码器是非条件的,这意味着在解码Y = [yτ | 1 ≤ τ ≤ T]中的yˆτ+1时,它不会向解码器ϕ提供条件数据点yˆτ = eT −τ+1,尽管条件预测器可以提供更好的结果。首先,条件自编码器充当提示,告诉预测器应该解码哪个后缀,而对自编码器本身提供了没有额外目的。其次,因为相邻事件通常具有显著的短期依赖关系,提供一个导致模型迅速学习短期依赖关系但忽略长期连接的条件并不是最优的。代码4.6显示了实现自编码器的代码片段。

4.4.4 事件分类器与

4.4.4 事件分类器与Anomaly Critic

使用嵌入层和自编码器仍然不足以实现我们的目标:预测一个序列是正常还是异常。因此,在深度自编码器之后,我们立即添加了一个额外的单层前馈神经网络γ进行预测。层γ充当一个多类分类器,接受解码器的输出Y作为输入,并生成概率矩阵P = [Pτ | 1 ≤ τ ≤ T],其中Pτ = [Pi | 1 ≤ i ≤ V ],而Pi可以被解释为离散事件et = eT −τ+1是离散事件键ki的实例的可能性。我们选择γ作为事件分类器,而不是一些典型异常检测自编码器中使用的标量重构误差,因为通过检查离散事件来识别时间敏感的异常更像是一个语言处理问题。我的意思是,我们可以将序列S视为句子,事件et视为单词,因此我们更关心措辞而不是嵌入,以找到合适的词和不合适的词,这等同于S中的正常事件和异常事件。

其次,类似于嵌入层,我们还在one-hot函数中包含序列开始、序列结束和未知。请注意,从one-hot表示生成的概率矩阵ˆP与X的顺序相反。因此,嵌入-编码器-解码器-分类器网络试图最小化以下函数:

狭义而言,该事件分类器γ的目标函数基于由以下公式定义的分类交叉熵损失:

在异常检测的措辞选项中,基于排名和基于阈值的方法是先前工作中采用的两种常见方法。为了与现有工作进行比较,DabLog采用了基于排名的标准,尽管它有一些缺点,这将在最后一部分进行讨论。假设离散事件et是kˆi的一个实例,基于排名的标准将考虑et是否异常,如果pi不在前N个预测中的话(如图4.4所示)。

4.5 超参数调整

有两组超参数设置,包括数据集调整和神经网络超参数。对于数据集处理,我们在数据处理部分已经提到,seqlen(序列长度)默认设置为10,开发者可以根据场景选择不同的日志键,0表示32,1表示78,2表示104,3表示1129。参数窗口大小指定每个序列的分钟数,默认设置为15。键分母表示键分母的数量,默认设置为100。

对于模型超参数,我们每个层有64个隐藏单元,两个隐藏层,批量大小为256。有关超参数的更多详细信息如下。对于异常标准,排名阈值为0.05,距离阈值为0.05。

4.6 模型部署

理想情况下,部署的模型可以实时确定一个事件和一个序列是否异常或正常。然而,有几个因素可能使模型部署变得非常具有挑战性。第一个因素是模型的吞吐量可能或可能不满足实时要求。为了满足所有实时要求,生产系统需要选择一个提供足够计算资源的平台(例如CPU、GPU、内存)。此外,应该注意容器化是部署深度学习模型的一种有用技术。因为容器(例如docker)使得扩展变得容易,它是模型部署的流行平台。容器化的代码还使得更新部署的模型变得更加简单。这减少了停机的可能性,并提高了维护效率。

第二个因素是是否有必要在边缘设备上部署模型。如果是这样,通常需要一个轻量级的模型执行环境,例如TensorFlow Lite。

4.7 评估

我们利用准确性和F1得分来比较不同模型的性能。

4.7.1 DabLog与基线的比较

首先,我们希望检查DabLog相对于基线预测器的优越性。对于基线,它类似于DeepLog[23]和nLSALog[89],两者都是由两层LSTM网络、一个多类分类器和一个基于排名的评论家实现的,如图4.5所示。与DabLog类似,我们没有直接使用one-hot表示,而是训练了一个定制的嵌入层。就像DeepLog和nLSALog一样,事件分类器由softmax函数激活,它们都利用基于排名的评论家来评估样本是否正常或异常。

图4.6和图4.7说明了基线和DabLog模型基于不同键的F1分数趋势。x轴表示规范化形式的变量排名阈值 θN = N |K∗| × 100%。它等效于使用Top-N阈值而不是|K∗|中的任何事件实例。Y轴表示模型的F1分数。除了DabLog和基线,我们还包括一个简单的频率模型,通过检查序列是否包含任何不是top-N最频繁键实例的事件来报告异常序列。

对于SOSP2009数据集,从图4.7a可以看出,基线在 θN = 10% 时达到了其峰值F1分数87.32%,而DabLog在 θN = 9% 时达到了其峰值F1分数97.18%。通过比较趋势,可以很容易得出结论,DabLog具有更高的峰值和更宽的范围,因此对于评论家而言,DabLog比基线和其他两个模型(DeepLog、nLSALog)更有优势。与图4.7b类似,DabLog在 θN = 6% 处达到峰值F1分数94.15%,而基线仅在 θN = 6% 处实现了F1分数80.47%。

对于UNSW-NB15数据集,从图4.6a和图4.6b可以看出,基线和DabLog都有平滑的曲线和宽广的平台,这意味着UNSW-NB15数据集具有较少的不频繁数据点。此外,它们都实现了类似的F1分数,但DabLog仍然具有略高的F1分数。因此,通过以上比较,DabLog比基线更具优势。

4.7.2 双向LSTM的优势

尽管结果表明DabLog更有优势,但理解其根本原因仍然有点抽象。因此,在这部分中,我们旨在介绍DabLog与双向LSTM以及基线和其他非双向LSTM之间的根本区别。

首先,我们说明DabLog在101个键和304个键上的精度比基线更好(如图4.8a所示)。这表明DabLog比基线更有优势,因为更高的精度意味着更低的假阳性率。图4.8b显示,虽然DabLog和基线的召回率都随着θN的增加而下降,但DabLog的下降速度较慢,因为基线无法识别结构异常序列,因此会有更多的假阴性。我们将在后面的部分对此进行解释。

正如我们所说,一些框架,如基线、DeepLog和nLSALog,无法识别结构异常序列,我们想借用DabLog的例子来解释这一点。

我们选择一个这样的案例,其中DabLog将一个异常案例报告为异常,而基线将其报告为正常。在此会话中,共有34个事件,这些事件列在表4.8中。DabLog报告了子序列s23、s28、s29和s30为异常,其中s23 = [e14, ... , e23],s30 = [e21, ... , e30]。这些子序列被认为是异常的,因为DabLog无法正确重构特别是第21个事件e21。也就是说,密钥k3在第21个事件e21的重构中不在前9%。前9%的重构包括k4、k5的变体、k6的变体="add StoredBlock: blockMap updated ...",以及k7="EXCEPTION: block is not valid ..."。这些事件键,除了k7之外,都是频繁键,每个都在数据集中占据0.1%以上。有趣的是,在这里DabLog期望不仅有频繁的键,还有一个极为罕见的事件键k7(占0.0017%),而这个键在k5之前。由于e21的前9%的重构中的这些期望键与异常、验证或blockMap更新相关,我们认为重构分布是为了与e23(与块传输相关)的因果关系而派生的,而不是为了e19(与块删除相关),尽管DabLog知道e19是被要求删除的,因为它已经正确地重构了e19。我们的解释是,DabLog期望在e21处有一个导致e23异常的原因,而在e23之前的缺乏因果关系使得序列在结构上异常。

相反,基线在s20 = [e11, . . . , e20]之后不预测e21是这些键中的任何一个。换句话说,基线不期望在e21处有一个原因,因为它无法预见e23 = k5。由于无法利用双向因果关系的基本局限性,基线无法检测到这样的结构异常会话。因此,我们认为,异常检测方法有必要将序列视为原子实例,并检查序列内的双向因果关系以及结构。像基线这样的单向异常检测无法识别结构异常的序列。

4.8 代码、数据以及其他问题

我们已经将我们的代码公开在GitHub上。

4.8.1 额外的方法和数据集

自编码器不是处理异常检测的唯一方法,还有其他一些序列重建解决方案,例如结合来自不同方向预测器的预测,也可能效果很好。我们还在我们的GitHub页面上提供了一个经过筛选的异常检测项目列表。此外,额外的数据集可能会有所帮助。DabLog需要包含低级事件和详细事件之间关系的数据集,例如系统调用事件。因此,我们提供了一个数据集数据库:loghub,其中包含一系列日志事件。

4.8.2 合并不同方法

有许多关于如何构建异常检测模型的不同想法,有人可能希望结合不同模型的优势。因此,可以构建混合模型。从表4.9中,我们可以看到两个模型输出的交集可以降低假阳性率。此外,诸如集成学习之类的组合模型可以帮助我们进一步提高整体深度学习性能。

4.8.3 嵌入层

虽然我们的嵌入层通过训练额外的嵌入层学习嵌入函数γ,但它仍然有处理未知事件键的缺点。例如,如果一个事件键不在训练数据中,那么它将被视为未知键,可能被错误地判断为异常事件。解决此问题的常见方法有两种。一种是我们添加罕见的事件,以便即使它是一个罕见的事件,未知也会得到训练。然而,在安全应用中,未知事件总是频繁发生的,错误地将未知事件视为罕见事件可能会导致假阳性率高。另一种选择是利用已训练的嵌入层,如Mimic嵌入[60],构建一个事件嵌入模型,将事件映射到嵌入。

4.8.4 预测标准

排名-based标准和阈值-based标准是以前异常检测方法采用的两种常见措辞选项。然而,排名-based和阈值-based标准都将概率分布粗暴地划分为正常和异常,而忽略了事件键之间的关系。问题在于,评论员可能会错误地将正常键视为异常,反之亦然。因此,我们想知道是否可以设计这样一个标准:将嵌入距离与排名-based标准结合起来,这意味着我们既有top-N阈值,又检查区域内邻居的标签。

Last updated