通过机器学习识别恶意 URLs
一、主要内容
识别恶意url,即将url分为正常的url和恶意url。属于机器学习中的二分类问题。本次实验使用逻辑回归[1]和 SVM 机器学习方法建立监测模型,对未知URLs进行恶意检测。
二、实验整体思路
-
分别拿到正常请求和恶意请求的数据集。
-
对无规律的数据集进行处理得到特征矩阵。
-
使用逻辑回归方式使用特征矩阵训练检测模型。
-
最后计算模型的准确度,并使用检测模型判断未知 URL 请求是恶意的还是正常的。
2.1 获取数据集[2]
good_fromE 某系统的某天的正常访问url,已去重
good_fromE2 同上
bad_fromE 利用sql注入某系统产生的url记录
badqueries 来源于网上数据(数据量较大)
goodqueries 来源于网上数据 (数据量较大)
恶意请求部分样本:
/top.php?stuff='uname >q36497765 #
/h21y8w52.nsf?<script>cross_site_scripting.nasl</script>
/ca000001.pl?action=showcart&hop=\"><script>alert('vulnerable')</script>&path=acatalog/
/scripts/edit_image.php?dn=1&userfile=/etc/passwd&userfile_name= ;id;
/javascript/mta.exe
/examples/jsp/colors/kernel/loadkernel.php?installpath=/etc/passwd\x00
/examples/jsp/cal/feedsplitter.php?format=../../../../../../../../../../etc/passwd\x00&debug=1
/phpwebfilemgr/index.php?f=../../../../../../../../../etc/passwd
/cgi-bin/script/cat_for_gen.php?ad=1&ad_direct=../&m_for_racine=</option></select><?phpinfo();?>
/examples/jsp/cal/search.php?allwords=<br><script>foo</script>&cid=0&title=1&desc=1
正常请求部分样本:
/rcanimal/
/458010b88d9ce/
/cclogovs/
/using-localization/
/121006_dakotacwpressconf/
/50393994/
/166636/
/labview_v2/
/javascript/nets.png
/p25-03/
/javascript/minute.rb
/javascript/weblogs.rss
/javascript/util.rtf
2.2 数据向量化
机器学习的算法需要输入一个固定结构的向量,而每一条url都没有特定的结构。故需要将每条url的文本特征转化成固定的数字特征。这里可以借鉴文本处理中将文本向量化的常用方法:TF-IDF.
TF-IDF 是一种用于资讯检索与文本挖掘的常用加权技术,被经常用于描述文本特征。
TF-IDF输入的是文本的词语,需要将url分词。我们选择通过长度为N的滑动窗口将文本分割为N-Gram序列。n越大 ,产生的字母组合种类越多(256n),产生的向量维度会更大,运算开销会增大,考虑到本机的性能,这里我们选择n=3。
// URL 请求
www.foo.com/1
// 经过分词后
[‘www’,‘ww.’,‘w.f’,’.fo’,‘foo’,‘oo.’,‘o.c’,’.co’,‘com’,‘om/’,‘m/1’]
经过TF-IDF处理,得到url的特征矩阵,由于很多特征向为0 ,所以该矩阵利用稀疏矩阵保存。输出格式是:
(0, 31445) 0.0739022819816
(0, 62475) 0.0629894240925
(0, 46832) 0.0589025342739
(0, 77623) 0.0717033170552
(0, 35908) 0.0882896248394
: 省略 :
特征矩阵的元素由 [ (i, j) weight] 三个元素组成,
i 对应于集合中的文档编号,j 对应于term编号(或者说是词片编号)
矩阵元素 [ (i, j) weight] 表示编号为 j 的词片在编号为 i 的文档下的 td-idf 值(weight)。
(0, 31445) 0.0739022819816 表示词片编号31445的在第0号文档的权值是 0.0739022819816
2.3 训练检测模型
2.3.1 LogisticRegression 模型
切分数据集
将数据集分为训练集和测试集。训练集用于训练模型,测试集则是根据训练集的训练结果来评判最终的训练效果。
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=666)
// x 是原始的特征矩阵
// y 是该条矩阵的分词对应的结果输出(正常是0 恶意是1)的列表
建立 LR 模型
lr = LogisticRegression()
lr.fit(x_train, y_train)
测试模型效果
lr.scores(x_test, y_test)
新 URLs 是否恶意预测
x_predict = ['待预测URL列表']
x_predict = vectorizer.transform(x_predict)
res = lgs.predict(x_predict)
2.3.2 SVM 模型
svm模型训练过程和逻辑回归模型类似,代码复用,只需将self.classifier 改成 svm.SVC()即可。
预测结果分析[3]
训练模型的正确率远远低于逻辑分类模型,训练时间也长于逻辑分类器。虽然在于识别错误上也一样全部识别出,不过该分类器的误报率太高,识别出来的结果没有说服力。
经查阅资料,svm对数据的异常点比较敏感,因为其训练只需要支持向量,有效样本本来就不高,一旦被干扰,预测结果难以预料。一般输入svm的数据维度不宜太高,我们训练的数据集有4117维,故我们决定在处理前加入降维模块。
选择用kmeans降维。该算法的主要思想是通过迭代过程把数据集划分为不同的类别,使得评价聚类性能的准则函数达到最优,从而使生成的每个聚类内紧凑,类间独立。
我们选择降维到80维度,加入降维后:
可见,对数据降维后svm运行的速度和正确率都大大提升了,错误url也能全部识别。
那是不是说明逻辑分类算法加入kmeans效果也会提升呢?
对此我们做了一个实验:
相对于原来的正确率有所下降,可见不同算法都有不同的适用场景。
三、总结
逻辑回归判断和svm都是常见的分类算法,区别:
- 从目标函数来看,区别在于逻辑回归采用的是logistical loss,svm采用的是hinge loss。
- 这两个算法损失函数的目的都是增加对分类影响较大的数据点的权重,减少与分类关系较小的数据点的权重。SVM的处理方法是只考虑support vectors,也就是和分类最相关的少数点,去学习分类器。而逻辑回归通过非线性映射,大大减小了离分类平面较远的点的权重,相对提升了与分类最相关的数据点的权重。
两者的根本目的都是一样。所以在很多实验中,两种算法的结果是很接近的。
四、局限与改进
局限
该实验使用的是监督学习下的二分类器。需要标定的数据集。然而在现实环境中,由于攻击方式的多样性,很难获得覆盖全面的恶意攻击url数据集,导致在面对 0day 攻击这类比较新的攻击url具有一定的脆弱性。
改进
参考一篇发表在Elsevier Science上的论文 McPAD:A Multiple Classifier System for Accurate Payload-based Anomaly Detection[4]
该论文指出,由于我们只有大量白样本,可以考虑通过单分类模型,学习单类样本的最小边界,边界之外的则识别为异常。通俗的讲,就是与其学习攻击的url特征,不如直接学习正常url的特征,拒绝所有不符合正常特征的url,以不变应万变。
参考文献
[1] Using Machine Learning to detect Malicious URLs https://medium.com/@faizann20/using-machine-learning-to-detect-malicious-urls-748d45f10dbf
[2] 用机器学习玩转恶意URL检测 https://www.freebuf.com/articles/network/131279.html
[3] 通过机器学习识别恶意url http://blog.csdn.net/solo_ws/article/details/77095341
[4] McPAD:A Multiple Classifier System for Accurate Payload-based Anomaly Detection https://www.sciencedirect.com/science/article/abs/pii/S1389128608003927