说一说基于机器学习算法的webshell检测

Posted by grt1stnull on 2017-11-16

只针对最近看到的两篇文章《Engineers at Work: Automatic Static Detection of Malicious JavaScript》与《lcatro/WebShell-Detect-By-Machine-Learning:使用机器学习识别WebShell》。

0x00.前言

笔者并没有针对性的研究机器学习在webshell上的检测,只是对两篇文章的总结与反思。我在微博上偶然刷到的两篇文章,加上我也对这一快比较感兴趣,所以对两篇文章做了相应的研读,并做了总结。

这两篇文章分别是Engineers at Work: Automatic Static Detection of Malicious JavaScriptlcatro/WebShell-Detect-By-Machine-Learning:使用机器学习识别WebShell。感谢作者所做的工作,这并不是毫无意义的。

0x01.Engineers at Work: Automatic Static Detection of Malicious JavaScript

因为我的博客还是以原创为主,所以没有把译文贴出来。并且参照着谷歌翻译,这篇文章很好理解。

1.简单介绍

在这篇文章里,作者是对恶意javascript脚本进行自动静态检测。其实,我们可以拓展到对webshell的检测。

首先作者对静态分析与动态分析(javascript)做了介绍:

静态分析:将脚本中的文本信息视为原始数据的唯一来源。计算在这个文本上的文本特征,估算概率,但是没有执行任何代码。

动态分析:通过互联网浏览器仿真评估脚本,可能获取关于JavaScript的真正功能以及安全性的更深入的信息。但是,这是以增加处理时间和内存使用量为代价的。

在这里,作者使用了静态分析的方法,因为:

使用静态文本特征,仍然有取得良好表现的可能性。我们的实验表明,静态分析可以产生可接受的结果,并具有简单、快速和低内存消耗等优点。

作者介绍的模型是n=grams模型:
webshell1
webshell2

其中,C(J)表示真实类别,良性的脚本为0、恶意的脚本为1。可以理解为对某个脚本的类别概率预测。M与B分别是恶意脚本与良性脚本。

对于某一语句,比如:

1
var x = 5;

如果拆分为单个字符,那么这句代码的形式会看起来像这样:

1
[‘v’, ‘a’, ‘r’, ‘ ‘, ‘x’, ‘ ‘, ‘=’, ‘ ‘, ‘5’, ‘;’]

这样个就会造成一种随机性,所以作者改为了根据关键字与类型的形式化(format)方法,形式如下:

1
[‘var’, ‘whitespace‘, ‘alphanumeric’, ‘whitespace‘, ‘punctuation’, ‘whitespace‘, ‘digit’, ‘punctuation’]

之后,作者奉上了总结:

尽管静态分析的潜力巨大,但问题只能得到了缓解,而没有完全解决。

完全克服混淆的唯一方法是动态分析。去混淆的浅动态策略包括用于评估和解压缩混淆的代码回到其原始形式的一系列技术。更复杂和动态的分析技术,其通常包括跟踪模拟浏览器环境中的脚本所采取的所有动作。

机器学习算法与语言模型(nlp)可以应用,以取得更好的效果。

2.我的总结

虽然作者只是写了一篇文章,没有开放什么代码,但是我们可以看出这种想法是可行的,并且有很多可以发扬光大的地方。

作者对代码语句的形式化(得到n-grams),与编译原理中的词法分析比较类似,这里值得我们注意。

还有一点是,我觉得作者这个模型,针对混淆效果会很不错。但是很多webshell,比如eval($_GET['cmd']),简单的一句话,就有点尴尬。如何对这种危险函数做处理也值得思考。

0x02.lcatro/WebShell-Detect-By-Machine-Learning:使用机器学习识别WebShell

1.简单介绍

这是一个来自与girhub的开源项目,使用了贝叶斯算法检测webshell。

git clone下来,整个目录结构是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
➜ ~ cd WebShell-Detect-By-Machine-Learning
➜ WebShell-Detect-By-Machine-Learning git:(master) ✗ tree
.
├── machine_learning_model.py
├── pic
│   ├── sample_test.png
│   ├── test.png
│   └── vector.png
├── readme.md
└── shell
├── normal-asp-code-0.asp
├── normal-jsp-code-0.jsp
├── normal-php-code-0.php
├── normal-php-code-1.php
├── normal-php-code-2.php
├── normal-php-code-3.php
├── shell-asp-eval-0.asp
├── shell-jsp-command-0.jsp
├── shell-php-assert-0.php
├── shell-php-assert-1.php
├── shell-php-assert-2.php
├── shell-php-assert-3.php
├── shell-php-assert-4.php
├── shell-php-call_user_func-0.php
├── shell-php-copy-0.php
├── shell-php-create_function-0.php
├── shell-php-create_function-1.php
├── shell-php-create_function-2.php
├── shell-php-create_function-3.php
├── shell-php-eval-0.php
├── shell-php-eval-1.php
├── shell-php-eval-2.php
├── shell-php-eval-3.php
├── shell-php-eval-4.php
├── shell-php-eval-5.php
├── shell-php-eval-6.php
├── shell-php-fwrite-0.php
├── shell-php-include-0.php
├── shell-php-include-1.php
├── shell-php-include-5.php
├── shell-php-popen-0.php
├── shell-php-preg_replace-0.php
├── shell-php-preg_replace-1.php
├── shell-php-preg_replace-2.php
├── shell-php-require-0.php
├── shell-php-require-4.php
└── shell-php-system-0.php
2 directories, 42 files

shell目录是使用的数据集,readme是原理与对代码的简单介绍;代码只有一个文件machine_learning_model.py,很简单并不复杂。

readme.md中,作者介绍了实现原理是使用朴素贝叶斯算法进行文本分类,然后介绍了一些函数。

首先是文本处理函数,作者定义了一个包含特殊符号的列表,他希望可以通过用空格替换这些特殊符号,将php代码通过空格分割开。

1
filter_flag_list = ['@','[',']','(',')','{','}','\'','"',',',';','=','.','\t','\n','\r\n']

然后定义了一个关键字列表,并只允许全局变量($_GET ,$_POST ,$_REQUEST ,$_COOKIE)的出现,对普通变量做了过滤

1
keyword = ['$_GET','$_POST','$_REQUEST','$_COOKIE']

之后是对数据集的加载,作者对数据集中不同类型的样本,定义了命名规则:样本类型-语言-代码类型-序号.拓展名,如normal-php-code-0.php

这个函数核心代码如下:

1
2
3
4
5
6
7
8
# classfy set
shell_sample = {}
# 样本类型:classfy_type
# 样本经过处理后的代码:php_code_vector
if not shell_sample.has_key(classfy_type) :
shell_sample[classfy_type] = []
shell_sample[classfy_type].append(php_code_vector)

最后一个函数的功能是对要检测的文件进行概率计算分类

简单描述下这个函数,首先对要检测的文件进行预处理,之后分别统计文件中的某个代码片段(即被空白分割的php代码)出现在各个类别脚本中的最大次数,然后计算概率(alpha=1),最后选择概率最大的类别。

2.我的总结

作者这个想法很不错。但是在算法方面,我比较担忧,因为贝叶斯对先验概率的使用。也可能是我对贝叶斯算法的理解与使用相对差一点的缘故吧。

还有一点是作者对样本的预处理,我觉得差劲一点,并且简单的计算概率emmmm,真是简单粗暴啊。虽然作者可能刚刚接触,但是这种动手精神还是值得我们学习的。

0x03.想法与总结

关于webshell与恶意脚本的检测,这两篇文章都给我们做了良好演示。

但是,凭借我对webshell的粗略了解,无论怎么进行混淆,它都是与正常文件看起来不一样的。通过文本特征的比较,我们可以对恶意文件,比如webshell进行检测。

这里,我主张对编译原理进行借鉴,来应用到恶意脚本检测领域。原因如下:

  1. 两篇文章的预处理过程,都是对词级的处理,与编译原理的词法分析器比较相似。
  2. 恶意脚本想要运行,一定是要可以通过编译器的。因此,我们可以对文本进行去混淆分析,或是直接做分析语法分析。

此外,我们不只可以对恶意脚本进行检测,还可以做更多东西。这里等以后有时间再做、再说吧,课业繁忙emmmmmm。

0x04.参考