首先来了解什么是决策树
决策树算法采用树形结构,使用层层推理来实现最终的分类。决策树由下面几种元素构成:
根节点:包含样本的全集
内部节点:对应特征属性测试
叶节点:代表决策的结果
预测时,在树的内部节点处用某一属性值进行判断,根据判断结果决定进入哪个分支节点,直到到达叶节点处,得到分类结果。这是一种基于 if-then-else 规则的有监督学习算法,决策树的这些规则通过训练得到,而不是人工制定的。
举个例子
给出如下的一组数据,一共有十个样本(学生数量),每个样本有分数,出勤率,回答问题次数,作业提交率四个属性,最后判断这些学生是否是好学生。最后一列给出了人工分类结果
然后用这一组附带分类结果的样本可以训练出多种多样的决策树,这里为了简化过程,我们假设决策树为二叉树,且类似于下图
通过学习上表的数据,可以设置A,B,C,D,E的具体值,而A,B,C,D,E则称为阈值,由此就可以生成决策树并进行分类
接下来看看scikit中决策树是怎么使用的。
下面是官方给出的例子
首先导入库,并简单给出数据,数组X存放训练样本,数组y存放训练样本的类标签
然后使用决策树分类器进行训练
执行通过之后,就可以使用该模型预测样本类别
也可以预测每个类的概率
这里用到的DecisionTreeClassifier不但可以用于二分类,也能用于多分类,我们使用scikit自带的iris数据集来试试
导入相关的库并调用分类器进行训练
接下来我们将决策树可视化,导入pydotplus绘图,调用export_graphviz以dot格式导出决策树并使用pydotplus绘图,并将图片保存为iris.pdf
查看iris.pdf
接下来我们再来了解什么是随机森林
如下所示
简单地说,随机森林是由很多决策树构成的,不同决策树之间没有关联。
当我们进行分类任务时,新的输入样本进入,就让森林中的每一棵决策树分别进行判断和分类,每个决策树会得到一个自己的分类结果,决策树的分类结果中哪一个分类最多,那么随机森林就会把这个结果当做最终的结果。
在scikit中要使用RandomForestClassifier分类器即可
接下来我们会通过scikit的决策树分类器来检测telnet暴力破解,并在此基础上加上随机森林分类器进行比对
先来介绍数据集
本次实验数据集来自kdd cup99
1998年美国国防部高级规划署(DARPA)在MIT林肯实验室进行了一项入侵检测评估项目。林肯实验室建立了模拟美国空军局域网的一个网络环境,收集了9周时间的TCPdump()网络连接和系统审计数据,仿真各种用户类型、各种不同的网络流量和攻击手段,使它就像一个真实的网络环境。这些TCPdump采集的原始数据被分为两个部分:7周时间的训练数据,大概包含5,000,000多个网络连接记录,剩下的2周时间的测试数据大概包含2,000,000个网络连接记录.
随后来自哥伦比亚大学的Sal Stolfo 教授和来自北卡罗莱纳州立大学的 Wenke Lee 教授采用数据挖掘等技术对以上的数据集进行特征分析和数据预处理,形成了一个新的数据集。该数据集用于1999年举行的KDD CUP竞赛中,成为著名的KDD99数据集。虽然年代有些久远,但KDD99数据集仍然是网络入侵检测领域的事实Benckmark,为基于计算智能的网络入侵检测研究奠定基础。
打开数据集可以看到是这样子的:
每条记录都有42项特征,最后一列是标记特征(Label),其他前41项特征共分为四大类
TCP连接基本特征(共9种,序号1~9)
TCP连接的内容特征(共13种,序号10~22)
基于时间的网络流量统计特征 (共9种,序号23~31)
基于主机的网络流量统计特征 (共10种,序号32~41)
这里我们要分析的telnet暴力破解,所以选取与此相关的特征即可,我们这里选择
TCP连接的内容特征(共13种,序号10~22)
(10) hot – 访问系统敏感文件和目录的次数,连续,范围是 [0, 101]。例如访问系统目录,建立或执行程序等。
(11) num_failed_logins – 登录尝试失败的次数。连续,[0, 5]。
(12) logged_in – 成功登录则为1,否则为0,离散,0或1。
(13) num_compromised – compromised条件出现的次数,连续,[0, 7479]。
(14) root_shell – 若获得root shell 则为1,否则为0,离散,0或1。root_shell是指获得超级用户权限。
(15) su_attempted – 若出现”su root” 命令则为1,否则为0,离散,0或1。
(16) num_root – root用户访问次数,连续,[0, 7468]。
(17) num_file_creations – 文件创建操作的次数,连续,[0, 100]。
(18) num_shells – 使用shell命令的次数,连续,[0, 5]。
(19) num_access_files – 访问控制文件的次数,连续,[0, 9]。例如对 /etc/passwd 或 .rhosts 文件的访问。
(20) num_outbound_cmds – 一个FTP会话中出站连接的次数,连续,0。数据集中这一特征出现次数为0。
(21) is_hot_login – 登录是否属于“hot”列表,是为1,否则为0,离散,0或1。例如超级用户或管理员登录。
(22) is_guest_login – 若是guest 登录则为1,否则为0,离散,0或1。
和基于时间的网络流量统计特征 (共9种,序号23~31)
(23) count – 过去两秒内,与当前连接具有相同的目标主机的连接数,连续,[0, 511]。
(24) srv_count – 过去两秒内,与当前连接具有相同服务的连接数,连续,[0, 511]。
(25) serror_rate – 过去两秒内,在与当前连接具有相同目标主机的连接中,出现“SYN” 错误的连接的百分比,连续,[0.00, 1.00]。
(26) srv_serror_rate – 过去两秒内,在与当前连接具有相同服务的连接中,出现“SYN” 错误的连接的百分比,连续,[0.00, 1.00]。
(27) rerror_rate – 过去两秒内,在与当前连接具有相同目标主机的连接中,出现“REJ” 错误的连接的百分比,连续,[0.00, 1.00]。
(28) srv_rerror_rate – 过去两秒内,在与当前连接具有相同服务的连接中,出现“REJ” 错误的连接的百分比,连续,[0.00, 1.00]。
(29) same_srv_rate – 过去两秒内,在与当前连接具有相同目标主机的连接中,与当前连接具有相同服务的连接的百分比,连续,[0.00, 1.00]。
(30) diff_srv_rate – 过去两秒内,在与当前连接具有相同目标主机的连接中,与当前连接具有不同服务的连接的百分比,连续,[0.00, 1.00]。
(31) srv_diff_host_rate – 过去两秒内,在与当前连接具有相同服务的连接中,与当前连接具有不同目标主机的连接的百分比,连续,[0.00, 1.00]
和telnet有关的记录我们可以看到
从上面两张图可以看到,涉及到telnet的有normal的话表示是正常登陆,guess_passwd则表示时在猜解密码,即暴力破解
接下来我们来写代码
首先加载数据
然后在其中选择最后一项标记为normal或者guess_passwd的且第三项为ftp的记录。这样就可以拿到ftp正常登陆或者是暴力破解的记录
接着需要进行特征工程,也就是提取特征,正如前面分析的,我们以TCP连接的内容特征(共13种,序号10~22)和基于时间的网络流量统计特征 (共9种,序号23~31)作为特征
然后就可以调用scikit的决策树分类器,并通过cross_val_score通过交叉验证得到评估的分数
测试结果如下
可以看到准确率还是很不错的
同样我们打印出决策树来
加上以下几行代码
将代码保存为dt-telnet1.py
运行即可得到dt.pdf
我们可以在此基础上增加几行代码,使用随机森林来检测telnet暴力破解,并比较其余决策树的效果,增加的代码如下
将代码保存为rf-telnet.py
测试
可以看到随机森林算法比决策树的算法的准确率更高
使用同样的代码我们还可以用于检测ftp的暴力破解,思路还是一样的,在决策树代码的基础上,我们只需修改代码中的这一行
测试如下
当然了,特征工程对于准确率也是有影响的,这里在检测telnet时只是粗略地选取了两大类特征,并复用到了ftp的检测上,如果要提高准确率可以根据要分析的行为选取更精细的特征,同学们可以自行尝试
参考:
1.https://easyai.tech/ai-definition/decision-tree/
2.https://zhuanlan.zhihu.com/p/30059442
3.https://scikit-learn.org/stable/modules/generated/sklearn.tree.export_graphviz.html
4.http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html
5.https://cloud.tencent.com/developer/article/1621977
6.《web安全与机器学习》
7.https://github.com/duoergun0729/1book/