我们基于WebShell的文本特征进行WebShell的检测。我们将互联网上搜集到的WebShell作为黑样本,当前最新的wordpress源码作为白样本。将一个PHP文件作为一个字符串处理,以基于单词的2-gram切割,遍历全部文件形成基于2-gram的词汇表,如图7-3所示。然后,进一步将每个PHP文件向量化。完整演示代码请见本书GitHub上的7-2.py。
图7-3 基于2-gram获取词汇表
1.数据搜集和数据清洗
定义函数,用于将PHP文件转换成一个字符串:
def load_file(file_path): t="" with open(file_path) as f: for line in f: line=line.strip('\n') t+=line return t
遍历样本集合,将全部PHP文件以字符串的形式加载:
def load_files(path): files_list=[] for r, d, files in os.walk(path): for file in files: if file.endswith('.php'): file_path=path+file print "Load %s" % file_path t=load_file(file_path) files_list.append(t) return files_list
针对黑样本集合,以2-gram算法生成全局的词汇表,其中2-gram基于单词切割,所以设置token的切割方法为:r'\b\w+\b'。
webshell_bigram_vectorizer = CountVectorizer(ngram_range=(2, 2), decode_error="ignore",token_pattern = r'\b\w+\b',min_df=1) webshell_files_list=load_files("../data/PHP-webSHELL/xiaoma/") x1=webshell_bigram_vectorizer.fit_transform(webshell_files_list).toarray() vocabulary=webshell_bigram_vectorizer.vocabulary_
其中,需要特别说明以下3个参数。
·ngram_range:设置成(2,2),表明基于2-gram;
·decode_error:设置成ignore,表明忽略异常字符的影响;
·token_pattern:设置成r'\b\w+\b',表明按照单词切割。
2.特征化
使用黑样本生成的词汇表vocabulary,将白样本特征化,其中非常重要的是设置CountVectorizer函数的vocabulary,这样才能以黑样本生成的词汇表来进行向量化:
wp_bigram_vectorizer = CountVectorizer(ngram_range=(2, 2), decode_error="ignore", token_pattern = r'\b\w+\b',min_df=1,vocabulary=vocabulary) wp_files_list=load_files("../data/wordpress/") x2=wp_bigram_vectorizer.fit_transform(wp_files_list).toarray() y2=[0]*len(x2) x=np.concatenate((x1,x2)) y=np.concatenate((y1, y2))
3.训练样本
创建NB实例:
clf = GaussianNB()
4.效果验证
我们使用三折交叉验证,所谓k折交叉验证,就是将数据集a分为训练集b和测试集c,在样本量不充足的情况下,为了充分利用数据集对算法效果进行测试,将数据集a随机分为k个包,每次将其中一个包作为测试集,剩下k-1个包作为训练集进行训练:
print cross_validation.cross_val_score(clf, x, y, n_jobs=-1,cv=3)
测试结果如下,准确率80%左右,还有提升空间。
[ 0.73584906 0.86538462 0.75 ]