Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/lcatro/webshell-detect-by-machine-learning

使用机器学习识别WebShell
https://github.com/lcatro/webshell-detect-by-machine-learning

Last synced: 25 days ago
JSON representation

使用机器学习识别WebShell

Awesome Lists containing this project

README

        

## 使用机器学习识别WebShell

学习样本在**shell** 目录,目前样本较少,疏漏之处在所难免,测试结果如下:

![pic/test.png](pic/test.png)

## 实现原理

实现原理是使用朴素贝叶斯进行文本分类.分类的样本包含正常的代码与WebShell 代码,为了方便后面的阅读,可以先阅读下面两个链接:

[朴素贝叶斯原理](http://blog.csdn.net/u012162613/article/details/48323777)
[朴素贝叶斯分类文本](http://www.cnblogs.com/XBWer/archive/2014/07/13/3840736.html)

站在朴素贝叶斯算法来看,代码其实就是一串文本,我们要做的第一件事就是要对文本进行处理,变成算法可以处理的形式

```python

def code_word_to_vector(php_code) :
filter_flag_list = ['@','[',']','(',')','{','}','\'','"',',',';','=','.','\t','\n','\r\n']
keyword = ['$_GET','$_POST','$_REQUEST','$_COOKIE']

for filter_flag_index in filter_flag_list :
php_code = php_code.replace(filter_flag_index,' ')

vector = php_code.split(' ')

for index in range(len(vector)) : # filter $ variant
if vector[index].startswith('$') and not vector[index] in keyword :
vector[index] = ''
elif vector[index] in keyword :
vector[index] = '$'

while vector.count('') : # filter empty item ..
vector.remove('')

return vector

```

预处理代码的算法做下面的工作:

1.`filter_flag_list` 只的是即将要过滤掉的字符,把它们替换成空格;`keyword` 的意思是,只保留这些关键的全局变量,那些无用的变量全部去除掉,否则变量名的文本在样本中和被检测的代码中也出现的话会影响概率计算结果

2.以空格字符作为分隔符,分割出所有的文本

3.过滤PHP 变量,只允许全局变量($_GET ,$_POST ,$_REQUEST ,$_COOKIE )的出现

4.从已经处理好的文本列表里面去除空内容(这里受到空格分隔符的影响,会有很多这样的空白内容)

代码处理后的效果

![](pic/vector.png)

处理完成代码之后,下一步就是加载数据集,来看看代码

```python

def load_and_train_model(data_set_path = 'shell') :
file_list = os.listdir(data_set_path)
shell_sample = {} # classfy set ..

for file_index in file_list :
try :
file_information = file_index.split('-')
classfy_type = file_information[0] + '-' + file_information[1] + '-' + file_information[2]
php_code_vector = shell_detect.code_word_to_vector(shell_detect.read_file(data_set_path + '\\' + file_index))

if not shell_sample.has_key(classfy_type) :
shell_sample[classfy_type] = []

shell_sample[classfy_type].append(php_code_vector)
except :
print 'Error Shell Sample File !' , file_index
print 'Sample File Name Format :'
print ' normal-%shell_language%-%shell_type%-%shell_index%.php or '
print ' shell-%shell_language%-%shell_type%-%shell_index%.php '

return shell_sample

```

加载数据集的代码主要做下面的工作:

1.根据指定的样本目录来读取训练的样本数据

2.样本数据文件的命名中包含了正常的代码和WebShell 的类型,命名规则为:**样本类型-语言-代码类型-序号.拓展名**,命名为normal-php-code-0.php 的文件的意思是这个样本文件是正常的PHP 代码文件,最后的0 代表着样本文件序号;命名为shell-php-eval-0.php 的意思是PHP 的eval() 函数的WebShell 样本文件

3.把这些样本文件读取出来预处理一下再放到样本集中

样本数据加载完成之后,接下来就是要对我们需要检测的文件做一个分类,思路是判断检测文件在各个样本中出现的概率,找到最大概率的那个就是对应的代码类别

```python

def try_classify(self,php_code) :
php_code_vector = shell_detect.code_word_to_vector(php_code)
alpha = 1
p_list = {}

for key_index in self.shell_sample.keys() :
max_p_value = 0

for shell_sample_index in self.shell_sample[key_index] :
found_vector_in_shell_sample_count = 0

for php_code_vector_index in php_code_vector :
if php_code_vector_index in shell_sample_index :
found_vector_in_shell_sample_count += shell_sample_index.count(php_code_vector_index)

p_value = (found_vector_in_shell_sample_count + alpha) / float(len(shell_sample_index) * 2 + alpha)

if p_value >= max_p_value :
max_p_value = p_value

p_list[key_index] = max_p_value

max_p_value = 0
max_p_type_name = ''

for p_type_name_index in p_list.keys() :
p_value = p_list[p_type_name_index]

if p_value >= max_p_value :
max_p_value = p_value
max_p_type_name = p_type_name_index

return max_p_type_name

```

分类函数的逻辑如下:

1.对要检测的代码进行预处理

2.遍历所有的样本文件,使用朴素贝叶斯算法对所有的样本进行概率计算

3.找到概率最大的那个样本的类别

4.返回最后分类的结果

代码处理与分类算法已经介绍完,样本也是重要的一部分,接下来我们来看一下样本的构造

```php

// shell-php-eval-0.php

// shell-php-eval-4.php

// shell-php-create_function-3.php

// shell-php-assert-1.php

// shell-php-preg_replace-1.php

// normal-php-code-0.php

// normal-php-code-2.php

```

样本的构造基本上是使用已知的WebShell 并且做一个归类.正常的代码这里只使用一些简单的PHP 语句,如果没有正常的代码,会导致概率的判断全部都会归类到WebShell 代码的范畴.

测试样本

```python

print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')
print 'Shell Type :' , model.try_classify('')

```

测试结果

![](pic/sample_test.png)