HacKerQWQ的博客空间

Web安全之机器学习算法

Word count: 1.5kReading time: 6 min
2022/05/05 Share

有监督学习算法

有监督学习算法主要有决策树、支持向量机(SVM)、朴素贝叶斯、K近邻、随机森林、逻辑回归。

K近邻算法

K近邻算法(k-nearest neighbors,KNN)是一种机器学习方法,根据你距离最近的k 个邻居来判断出你的分类。也就是说,如果离你最近的K个邻居中有5个a分类,2个b分类,那你就属于a分类。可以看出,KNN做分类预测时,一般是选择多数表决法。
KNN不只能做分类,而且可以做回归。我们知道回归一般对连续值进行预测,KNN算法就是用K个邻居的平均值作为预测值。

KNN常用的算法为:

  • Brute Force;
  • K-D Tree
  • Ball Tree。

简单记忆:对于小型数据集,使用Brute Force,对于低维数据,选择K-D Tree,对于高维数据,选择Ball Tree。

代码示例

使用sklearn.neighbors库做演示,详细用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.neighbors import NearestNeighbors
import numpy as np

X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
# n_neighbors代表k值,algorithm是算法
nbrs = NearestNeighbors(n_neighbors=2, algorithm='ball_tree').fit(X)

#distances表示距离最近的点的距离的集合,indies包含距离最近的点的索引
distances, indices = nbrs.kneighbors(X)

print(distances)
print(indices)

# KNN的加权图的可视化
print(nbrs.kneighbors_graph(X).toarray())

image-20220511130213645

结果预测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from sklearn.neighbors import NearestNeighbors
from sklearn.neighbors import KNeighborsClassifier
import numpy as np


X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
Y = np.array([1,1,0,1,1,0])
nbrs = KNeighborsClassifier(n_neighbors=2)
nbrs.fit(X,Y)

# 预测点
print(nbrs.predict([[1.1,1.5]]))
# 返回单个点的概率估算
print(nbrs.predict_proba([[-1,-2]]))

image-20220511132651834

异常操作检测

数据集

数据集:Masquerading User Data

数据集中包含50个User各15000条命令,对命令进行100一组的分块,前50组命令没有恶意操作,后100组命令随机包含恶意操作,恶意操作标记为1,非恶意则为0,标记文本在此下载,另外,标记文本只包含后100组的结果,训练过程中前50组的0需要自己补齐。

使用前100组作为训练集,后50组作为测试集。

在标记文本中包含50列,100行,第i列代表Useri,第i行代表对应User的第i个命令块的标记结果

image-20220512170839798

SEA伪装者检测1

思路:以命令块为单位即100个命令一组进行K近邻算法训练,每个命令块以出现命令的个数、出现命令与使用频率最高的50个命令的重复数,出现命令与使用频率最低的50个命令的重复数作为每个命令块的特征输入进行训练。

代码存放在此:https://github.com/HacKerQWQ/CyberSecurity_MachineLearning/blob/master/KNN/intrusion_detection_1.py

频率需要使用到nltk的probability库中的FreqDist方法

1
from nltk.probability import FreqDist

获取频率最高的50个和最低的50个命令

1
2
3
4
# dist包含该用户所有命令键值对,命令:出现个数的形式
fdist = list(FreqDist(dist).keys())
dist_max=set(fdist[0:50])
dist_min = set(fdist[-50:])

生成特征

1
2
3
4
5
6
7
8
f1=len(set(cmd_block))
fdist = list(FreqDist(cmd_block).keys())
f2=fdist[0:10]
f3=fdist[-10:]
f2=len(set(f2) & set(dist_max))
f3=len(set(f3)&set(dist_min))
x=[f1,f2,f3]
user_cmd_feature.append(x)

x的格式如下

[29, 10, 0]
[29, 10, 0]
[23, 6, 1]
[6, 6, 0]
[15, 9, 1]
[16, 10, 0]

最后对数据进行训练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 训练集取前100组
x_train=user_cmd_feature[0:N]
y_train=y[0:N]

# 测试集取后50组
x_test=user_cmd_feature[N:150]
y_test=y[N:150]

# 模型训练
neigh = KNeighborsClassifier(n_neighbors=3)
neigh.fit(x_train, y_train)
# 预测结果
y_predict=neigh.predict(x_test)

# 计算预测结果和实际结果的准确率
score=np.mean(y_test==y_predict)*100

print(score)

# 输出分类结果报告
print(classification_report(y_test, y_predict))

# 计算混淆矩阵以评估分类的准确性。
print(metrics.confusion_matrix(y_test, y_predict))

结果如下:

image-20220512172947519

最终结果表现为94%的准确率

SEA伪装者检测2

思路:跟上一步的区别在于这次训练的使用的特征由操作命令向量组成,进行全量比较。

代码:https://github.com/HacKerQWQ/CyberSecurity_MachineLearning/blob/master/KNN/intrusion_detection_2.py

操作命令向量生成:

1
2
3
4
5
6
7
8
user_cmd_feature=[]
dist = list(dist)
for cmd_list in user_cmd_list:
v=[0]*len(dist)
for i in range(0,len(dist)):
if dist[i] in cmd_list:
v[i]+=1
user_cmd_feature.append(v)

v如下

image-20220512183512003

最后使用交叉验证,10次随机取样和验证

1
print(cross_val_score(neigh,user_cmd_feature,y,n_jobs=-1,cv=10))

结果为

image-20220512184108940

Rootkit检测

数据集

选用KDD99数据集:http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html

数据格式如图

image-20220513115445607

Rootkit检测过程

总共41个特征,根据官网给出的特征表,选用中间10-22个特征。

image-20220513123019727

思路:选用基于telnet协议的流量进行研究,将normal标记为0,rootkit标记为1,10-22共13个特征作为输入,使用KNN作为算法进行模型训练和预测。

以下是提取telnet协议的流量,并且生成y数据集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def get_rootkit2andNormal(x):
v=[]
w=[]
y=[]
for x1 in x:
if ( x1[41] in ['rootkit.','normal.'] ) and ( x1[2] == 'telnet' ):
if x1[41] == 'rootkit.':
y.append(1)
else:
y.append(0)

x1 = x1[9:21]
v.append(x1)

for x1 in v :
v1=[]
for x2 in x1:
v1.append(float(x2))
w.append(v1)
return w,y

KNN训练并且使用K折验证效果

1
2
clf = KNeighborsClassifier(n_neighbors=3)
print(cross_val_score(clf, x, y, n_jobs=-1, cv=10))

image-20220513124409273

Webshell检测

数据集

数据集使用ADFA-LD,文件夹中包括训练集、攻击数据集,包含Linux和Windows的系统调用对应的数字代码。

image-20220513145516687

Webshell检测过程

这里使用Attack_Data_Master文件夹下的Web_Shell系列文件夹下的文本文件以及Training_Data_Master下的文本文件作为训练集。

采用词袋模型处理训练集形成向量

1
2
3
vectorizer = CountVectorizer(min_df=1)
x=vectorizer.fit_transform(x)
x=x.toarray()

image-20220513145905681

将training文件夹下的文件输入的数据标记为0,attack文件夹下的则标记为1.

使用KNN训练

1
clf = KNeighborsClassifier(n_neighbors=3)

效果验证

1
2
3
scores=cross_val_score(clf, x, y, n_jobs=-1, cv=10)
print(scores)
print(np.mean(scores))

image-20220513150129630

平均有96%的准确率。

参考链接

CATALOG
  1. 1. 有监督学习算法
    1. 1.1. K近邻算法
      1. 1.1.1. 代码示例
      2. 1.1.2. 异常操作检测
        1. 1.1.2.1. 数据集
        2. 1.1.2.2. SEA伪装者检测1
        3. 1.1.2.3. SEA伪装者检测2
      3. 1.1.3. Rootkit检测
        1. 1.1.3.1. 数据集
        2. 1.1.3.2. Rootkit检测过程
      4. 1.1.4. Webshell检测
        1. 1.1.4.1. 数据集
        2. 1.1.4.2. Webshell检测过程
        3. 1.1.4.3. 效果验证
  2. 2. 参考链接