网络安全中的 Machine Learning:训练监督式模型以检测 DGA 活动
当您接到使用随机电话号码打来的推销电话时,该有多烦人?即使您屏蔽了这个号码,也没什么用,因为下一个电话是用一个全新的号码打来的。网络攻击者也会采用同样的卑鄙伎俩。恶意软件创建者通过使用域名生成算法 (DGA),可更改他们命令和控制基础架构的来源,从而逃避检测,令试图阻止其活动的安全分析师非常恼火。
这个系列内容包含两篇博文,我们将学习如何使用 Elastic Machine Learning 来构建和评估用于检测域名生成算法的模型。在第 1 部分中,我们将介绍以下内容:
- 从原始恶意域名和良性域名提取特征的过程
- 简单介绍一下寻找合适特征的过程
- 展示如何使用 Elastic Stack 来训练和评估 Machine Learning 模型
在第 2 部分中,我们会讨论如何将训练的模型部署到采集管道中,以在采集时扩充 Packetbeat 数据。配置文件和支持资料将在示例存储库中提供。
如果您想在家中尝试这一操作,建议注册我们的免费试用 Elasticsearch Service,从中您可以完全使用我们所有的 Machine Learning 功能。好吧,下面我们开始深入探讨。
DGA:背景
感染目标计算机后,许多恶意程序会试图联系远程服务器(也就是所谓的命令及控制(C&C 或 C2)服务器),以窃取数据并接收指令或更新。这意味着,恶意二进制文件必须知道 C&C 服务器的 IP 地址或域名。如果此 IP 地址或域名被硬编码到二进制文件,则对于防御措施而言相对会容易些,通过将域名添加到阻止列表即可挫败这种通信。
为了暗中破坏这种防御措施,恶意软件作者可能会将 DGA 添加到他们的恶意软件中。DGA 可生成数百上千的随机化域名。然后,受感染计算机上的恶意软件二进制文件会循环遍历每个生成的域名,试图解析域名,以查看哪个域名已注册为 C&C 服务器。域名的庞大数量和随机性使得基于规则的防御方法很难阻断这种通信渠道。另外,由于 DNS 流量通常会非常大,这也使得人工分析师难以发现。这两个因素使得 Machine Learning 成为理想的解决方案。
训练 Machine Learning 模型来对域名分类
在监督式 Machine Learning 中,我们提供了打标的恶意域名和良性域名的训练数据集,让模型先基于该数据集进行学习,然后使用模型将以前未见过的域名分类为恶意域名或良性域名。
有各种不同类型的 DGA,并非所有的 DGA 看上去都相同。有些 DGA 会生成随机化的域名,而有些会使用单词表。对于生产模型,可以采用不同的特征和模型来捕获不同算法的特性。在本示例中,我们将根据最常见算法中发现的特性来训练单个模型。
以下是我们将用于训练模型的数据集,其中既有各种恶意软件家族的域名,也有良性域名。
cryptolocker
、banjori
和 suppobox
恶意软件家族生成的示例域名
特征工程
为创建有效的 Machine Learning 模型,需要输入相应的特征,用于表达 DGA 所生成域名的特性。因此,我们必须告诉模型,字符串的哪些方面对于区分恶意域名和良性域名是重要的。这在 Machine Learning 领域称为特征工程。
掌握最能区分良性域名和恶意域名的特征是一个迭代的过程。例如,我们从域名长度和域名熵等一些简单特征开始,但是与其他方法(如 LSTM)相比,生成的模型并不是特别准确。这些模型利用了字符串的序列特性,因此,我们随后研究了能更有效编码序列的其他特征。
在迭代了几种特征工程方法之后,我们得出以下结论:使用字符串中存在的各种长度的子串,可以最有效地体现模型中恶意域名和良性域名之间的差异。
这些子串通常称为 n 元语法。在开发特征时,需要权衡两个方面,一是特征的数量(训练数据集的维数)和计算特征的复杂性;二是它们对模型的好处。在对各种长度的 n 元语法进行迭代和测试之后,我们发现,长度为 4 或更长的 n 元语法并不能对模型的预测信息有显著提升,因此,我们将特征集限定于一元语法、二元语法和三元语法。图 3 中的示意图说明了如何从示例域名中生成这些特征。
要生成将每个 DGA 域名拆分为一元语法、二元语法和三元语法的 Elasticsearch 索引,您可以通过具有 Painless 脚本处理器的采集管道重新索引原始源索引。下面的图 4 中显示了一个示例。 有关完整的配置、说明和各种定制选项,请参阅示例存储库。
POST _scripts/ngram-extractor-reindex { "script": { "lang": "painless", "source": """ String nGramAtPosition(String fulldomain, int fieldcount , int n){ String domain = fulldomain.splitOnToken('.')[0]; if (fieldcount+n>=domain.length()){ return '' } else { return domain.substring(fieldcount, fieldcount+n) } } for (int i=0;i<ctx['domain'].length();i++){ ctx[Integer.toString(params.ngram_count)+'-gram_field'+Integer.toString(i)] = nGramAtPosition(ctx['domain'], i, params.ngram_count) } """ } }
通常情况下,需要进行更多的预处理,才能将长度为 1、2 和 3 的子串转换为用于 Machine Learning 算法的数值矢量。在我们的例子中,Elastic Machine Learning 将负责这个转换为数值的过程,也就是所谓的编码。Elastic Machine Learning 还将检查特征,并自动选择那些携带最多信息的特征。
创建数据帧分析作业
下一步是使用数据帧分析 UI 来创建分类作业。在下面的屏幕截图中,我突出标注了此过程的一些重要设置。
需要注意的一点是,我们可以使用滑块指定训练/测试拆分。在图 5 的屏幕截图中,训练/测试拆分设置为 80%,这意味着,源索引中 80% 的文档将用于训练模型,而其余 20% 将用于测试模型。
训练过程完成后,我们可以导航到数据帧分析结果 UI 来评估模型的性能。由于我们将源索引拆分为训练集和测试集,因此我们将能够看到模型在每个数据集上的性能。虽然训练性能和测试性能都可以提供有价值的信息,但在这种情况下,我们会对测试数据集上的模型性能更加感兴趣,因为它能让我们模型中的泛化误差。此误差表明模型将如何对之前从未遇到过的数据点进行分类。
评估 Machine Learning 模型
训练过程完成后,我们可以单击“查看”,以进入“Elastic Machine Learning UI 作业管理”页面来查看结果。
结果页面(见图 6)为我们提供了两个关键信息:一个混淆矩阵 — 汇总了我们模型的执行情况;一个结果表 — 可以详细查看模型是如何对各个数据点进行分类的。我们可以使用表格右上方的“测试”/“训练”筛选器,在测试和训练数据集的混淆矩阵和汇总表之间进行切换。
显示模型性能的一种常见方法是使用称为混淆矩阵的可视化。混淆矩阵显示归类为真正类(模型标识为恶意且实为恶意的恶意域名)和真负类(模型标识为良性的良性域名)的数据点的百分比,以及模型将其中的良性域名与恶意域名相混淆(假正类或假负类)的文档的百分比。
顾名思义,混淆矩阵会迅速向我们展示一个模型是否经常将一个类的实例混淆为另一个类。
在图 6 中,我们看到模型对测试数据的真正类率为 98%。这意味着,如果我们将这个模型部署到生产环境中,对传入的 DNS 数据进行分类,我们大概会看到 2% 的假正类率。虽然这看似是一个相当低的数字,但很高的 DNS 流量意味着它仍将导致相当高的警报率。在第 2 部分中,我们将研究如何使用异常检测来减少误报的数量。
结论
在本博文中,我们简要概述了如何使用 Elastic Machine Learning 构建和评估用于 DGA 检测的 Machine Learning 模型。我们研究了从原始恶意域名和良性域名提取特征的过程,并稍微介绍了一下有关寻找合适特征的过程。最后,我们了解了如何使用 Elastic Stack 来训练和评估 Machine Learning 模型。
在本系列的下一部分中,我们将介绍如何在采集管道中使用推理处理器来部署此模型,以借助域名恶意性的预测来扩充传入的 Packetbeat 数据,以及如何使用异常检测作业来减少误报的数量。同时,请免费试用我们的 Machine Learning 功能,看看在您识破数据中的噪音时能揭示出什么洞见。