目录

“文章部分内容引用自兜哥作品”

0x01 机器学习衡量指标

0x02 数据集

0x03 特征提取

0x04 模型训练及检测

0x05 预测新样本

0x06 优化检测

前言

本人是合合信息(划重点——“OCR+AI大数据公司”)安全部门的一名成员,受到公司AI氛围的感染,对于不会AI技术的我深感不适,便决心学习一波AI技术。AI是什么?我们把AI定义为让计算机模仿人类智能来处理事情的技术,目前,AI技术已经在有限的简单领域内取得非常大的成功。强行举个栗子,有研究人员写了一个在《打砖块》游戏中打到最高分的AI程序,它可以自己学习进步,并在2个半小时内就打得比人类玩家更好。

研究人员运行了这个程序,让他们惊讶的是,这个程序发展出了一套软件里没有写过的策略。它会专攻砖块上的一个点,直到凿出洞来,再穿到墙后。在这套策略下,计算机无需不停移动球板,工作量降到了最低。同时,这也让球板漏接球的可能性降到最低。

我们要知道,计算机是看不见游戏界面上的小球、球板和砖块的。它“看见”的只是一堆数字。它知道自己能控制的变量,以及如何运用变量来提高分数。

AI在安全领域也是处在起步阶段,很多安全问题都没有很好的AI解决方案,今天我们就来实践一个安全里面的二分类问题——webshell的识别检测。

  • 什么是webshell?

Webshell是一种基于web应用的后门程序,是黑客通过服务器漏洞或其他方式提权后,为了维持权限所部署的权限木马。Webshell的危害非常大,通常为网站权限,可以对网站内容进行随意修改、删除,甚至可以进一步利用系统漏洞对服务器提权,拿到服务器权限。

  • 解决方法:

webshell检测方法较多,有静态检测、动态检测、日志检测、语法检测、统计学检测等等。本文重点讨论webshell的静态检测方法,静态检测也是最主要的检测手段。

静态检测通过匹配特征码、特征值、危险函数函数来查找webshell的方法,只能查找已知的webshell,并且误报率漏报率会比较高,但是如果规则完善,可以减低误报率,但是漏报率必定会有所提高。优点是快速方便,对已知的webshell查找准确率高,部署方便,一个脚本就能搞定。缺点漏报率、误报率高,无法查找0day型webshell,而且容易被绕过。

机器学习最大的优点是它具有泛化能力,也就是可以举一反三。基于机器学习的webshell检测可以有效的提升准确率和减低漏报率。本文使用的算法为兜哥的opcode+tfidf算法。如下是常规检测和机器学习检测率的比较。

0x01 机器学习衡量指标

  • 混淆矩阵

混淆矩阵(Confusion Matrix)又被称为错误矩阵,通过它可以直观地观察到算法的效果。在二分类问题中,可以用一个2×2的矩阵表示,如下表所示。其中,FP为表示实际为假预测为真,也就是误报,FN表示实际为真预测为假,也就是漏报。

  • 准确率和召回率

机器学习中最常用的指标就是准确率和召回率。准确率也叫查准率,要提高查准率就要降低误报。召回率也叫查全率,要提高查全率就要降低漏报。

  • F1-Score

人们通常使用准确率和召回率这两个指标,来评价二分类模型的分析效果。但是当这两个指标发生冲突时,我们很难在模型之间进行比较。此时可以使用F1-score来进行综合评判。

0x02 数据集

所用数据集均来源于github,需要两类数据,黑名单和白名单。白名单可以从以下链接获取。

https://github.com/topics/php?o=desc&s=stars

黑名单使用以下项目:

https://github.com/tennc/webshellhttps://github.com/ysrc/webshell-samplehttps://github.com/tanjiti/webshellSample

由于github下载速度较慢,以下是github中star排名前350的php项目的白名单和12个webshell项目的黑名单的备份。测试算法时可以只需取部分项目即可。

链接: https://pan.baidu.com/s/12FWAN-jIWTqjOlwB5V0DuQ 提取码: 31bi

0x03 特征提取

1.词袋和TF-IDF模型

词袋模型是指将句子或文本中的每个单词看成一个集合,并统计其出现的次数。词袋模型被广泛应用在文件分类,词出现的频率可以用来当作训练分类器的特征。对一篇文章进行特征化,最常见的方式就是词袋。

TF-IDF(词频-逆文本频率指数)模型是一种用以评估一个词对于一个文件集或一个语料库中的其中一份文件的重要程度。一个字词的重要性随着它在文件中出现的次数成正比增加,同时会随着它在语料库中出现的频率成反比下降。

函数get_feature_by_tfidf的作用是传文本数组进去,可以返回一个特征矩阵,原理就是使用词袋和TF-IDF模型计算文本特征。

def get_feature_by_tfidf(x, max_features=None):    cv = CountVectorizer(ngram_range=(3, 3), decode_error="ignore",                         max_features=max_features,token_pattern=r'\b\w+\b',                          min_df=1, max_df=1.0)    x = cv.fit_transform(x).toarray()    transformer = TfidfTransformer(smooth_idf=False)    transformer = transformer.fit_transform(x)    x = transformer.toarray()    return x

2.opcode模型

opcode是计算机指令的一部分,也叫字节码,一个php文件可以抽取出一个指令序列,如ADD、ECHO、RETURN。由于直接对php文件使用词袋和TF-IDF进行模型训练会消耗大量计算资源,使用opcode模型进行降维可以有效提升模型效率和模型的准确率。由于opcode只关心操作指令,不关心函数名、定义等,因此可以有效的检测一些加密、混淆的代码。

要使用opcode模型,需要装一个vld的扩展,需要注意的是不同版本的vld支持不同版本的PHP,如vld 0.11.1版本支持PHP 5.4,vld 0.13.0支持PHP 5.6。下载链接如下:

Windows:http://pecl.php.net/package/vld/0.14.0/windows

Linux:http://pecl.php.net/package/vld

Windows下载的是dll文件,只需将其中的php_vld.dll放到PHP安装目录/ext目录下,编辑php.ini文件添加extension=php_vld.dll即可。

Linux的安装命令如下,安装完后配置php.ini,将extension=vld.so添加进去。

tar zxvf vld-0.xx.x.tgzcd vld-0.xx.xphpize./configuremake && make install

安装完成后,使用php -dvld.active=1 -dvld.execute=0 1.php即可获取1.php文件的opcode。对于<?php echo "test"; ?>的opcode序列为ECHO RETURN,如下图所示:

对于一句话<?php @eval($_POST['a']);?>的opcode序列为BEGIN_SILENCE FETCH_R FETCH_DIM_R INCLUDE_OR_EVAL END_SILENCE RETURN,如下图所示:

函数load_php_opcode的作用是提取一个php文件的opcode序列。

def load_php_opcode(php_filename):    try:        output = subprocess.check_output(['php.exe', '-dvld.active=1',                                          '-dvld.execute=0', php_filename],                                         stderr=subprocess.STDOUT)        tokens = re.findall(r'\s(\b[A-Z_]+\b)\s', output)        t = " ".join(tokens)        return t    except:        return " "

由于提取opcode会消耗较多的时间,函数load_php_opcode_from_dir_with_file会提取一个文件夹中所有php文件的opcode到指定的文件中,作为训练和预测时的特征文件。

def load_php_opcode_from_dir_with_file(dir, file_name):    print "load php opcode from dir => " + dir    for root, dirs, files in os.walk(dir):        for filename in files:            if filename.endswith('.php'):                try:                    full_path = os.path.join(root, filename)                    file_content = load_php_opcode(full_path)                    with open(file_name, "a+") as f:                        f.write(file_content + "\n")                except:                    continue

0x04 模型训练及检测

1.朴素贝叶斯算法

本文使用16667个样本,其中白样本为14467条,黑样本为2200条,白样本远大于黑样本,以下是使用朴素贝叶斯算法的代码。

def do_gnb(x, y):    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4,                                                         random_state=0)    clf = GaussianNB()    clf.fit(x_train, y_train)    joblib.dump(clf, 'model/gnb.pkl')    y_pred = clf.predict(x_test)    do_metrics(y_test, y_pred)

经测试,使用朴素贝叶斯算法的准确率为54.5%,召回率为98.4%,其中,有14个样本漏报,715个样本误报,效果较差。对于黑白样本不均,不推荐使用朴素贝叶斯算法。

2.随机森林算法

以下是随机森林的算法代码实现。

def do_rf(x, y):    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.4,                                                         random_state=0)    clf = RandomForestClassifier(n_estimators=50)    clf.fit(x_train, y_train)    joblib.dump(clf, 'model/rf.pkl')    y_pred = clf.predict(x_test)    do_metrics(y_test, y_pred)

使用随机森林算法的准确率为94.4%,召回率为91.5%,效果相比朴素贝叶斯好。

0x05 预测新样本

1.预测单个文件需要注意的是,由于采用TF-IDF模型进行特征提取,在预测新样本时,要加载训练时的黑白样本特征作为语料库,进而计算出新样本的特征矩阵。加载语料库的代码如下:

def get_old_data():    white_file_list = []    black_file_list = []    with open('black_opcodes.txt', 'r') as f:        for line in f:            black_file_list.append(line.strip('\n'))    with open('white_opcodes.txt', 'r') as f:        for line in f:            white_file_list.append(line.strip('\n'))    old_data = white_file_list + black_file_list    return old_data

在训练样本时,程序将所有样本分成了两部分,一部分拿去训练得到模型,一部分使用训练出来的模型拿来做预测,检测该模型的效果。当算法确定后,就需要将所有样本拿来训练获得最终的训练模型。

def do_rf_fin(x, y):    clf = RandomForestClassifier(n_estimators=50)    clf.fit(x, y)    joblib.dump(clf, 'model/rf_fin.pkl')

最后,我们再使用训练出的rf_fin.pk1模型做预测:

if __name__ == '__main__':    php_file_name = sys.argv[1]    print 'Checking the file {}'.format(php_file_name)    all_file = get_old_data()    opcode = load_php_opcode(php_file_name)    all_file.append(opcode)    x = get_feature_by_tfidf(all_file)    gnb = joblib.load('save/rf_fin.pkl')    y_p = gnb.predict(x[-1:])    if y_p == [0]:        print 'Not Webshell'    elif y_p == [1]:        print 'Webshell!'

2.预测一个文件夹

if __name__ == '__main__':    php_file_dir = sys.argv[1]    log('Checking the dir {}'.format(php_file_dir))    checked_file_num = 0    webshell_file_num = 0        # 准备数据    opc_list, file_list = load_php_opcode_from_dir(php_file_dir)    all_file = get_old_data()    for i in opc_list:        checked_file_num = checked_file_num + 1        all_file.append(i)    x = get_feature_by_tfidf(all_file)    # end 准备数据    gnb = joblib.load('model/rf_fin.pkl')    y_p = gnb.predict(x[-checked_file_num:])    for i in range(len(y_p)):        if y_p[i] == 1:            webshell_file_num = webshell_file_num + 1            log(file_list[i] + " => webshell!")    log("All php file number: " + str(checked_file_num) + " | webshell number: "         + str(webshell_file_num))

尝试扫描,结果如下:

0x06 优化检测率

1.优化数据集

本文主要从数据集的角度进行检测率的优化。优化数据集分为两方面,一方面是增大数据量,数据量越大,预测的效果越好,本次测试黑样本较少,另一方面是清洗数据集,主要针对的是黑样本的清洗。

在预测的过程中,发现模型会将空文件或者没有php代码的文件识别为webshell,这些文件的opcode序列为ECHO RETURN,回过头找黑名单中opcode序列为ECHO RETURN的webshell文件,发现很多webshell的代码使用的是php短标签 ?>,而php.ini没有配置短标签支持,导致这些短标签的webshell不能被php正常解析,最终和普通txt文件的opcode相同,产生了数据集污染,将正常的空文件或文本文件识别成了webshell。如下图所示:

修改php.ini,将短标签解析开启short_open_tag = On,重新进行特征提取,发现还是存在少量ECHO RETURN序列,直接手工去除,再次训练。

使用朴素贝叶斯的效果如下,并没有提高准确率和召回率,还有所下降,说明朴素贝叶斯在此不适用。由于之前去掉了一部分黑名单样本导致黑白样本数量差距变大,导致朴素贝叶斯分类效果变差。

而使用随机森林的准确率和召回率有大幅提升,准确率为97.8%、召回率为96.5%,分别提升了3.4%和5%,随机森林不受黑白样本数量干扰,分类效果较好。

对于数据集还可以继续优化,还存在一些小问题没去发现,在此不再做扩展。

2.优化算法

实践发现,基于这些数据集的情况下,随机森林算法的效果要优于朴素贝叶斯,优化算法可以使用如深度学习的CNN、RNN等算法进行尝试。

3.优化参数

参数优化主要分为算法模型调参和特征提取调参,这里主要可调的参数为N-Gram数和词袋最大特征数。

这里主要介绍一下N-Gram,N-Gram模型是基于“联想”,它的一个特点是某个词的出现依赖于其他若干个词,第二个特点是我们获得的信息越多,预测越准确。例如听到腾讯就想到qq,听到百度,阿里就会想到腾讯,腾讯、qq就相当于2-Gram,百度、阿里、腾讯相当于3-Gram。

上文所使用的是3-Gram,其中参数ngram_range是指定ngram的范围,也可以使用ngram_range=(2,3)表示同时使用2-Gram和3-Gram。

cv = CountVectorizer(ngram_range=(3, 3), decode_error="ignore",                         max_features=max_features,token_pattern=r'\b\w+\b',                          min_df=1, max_df=1.0)

这里在使用2-Gram进行训练,即ngram_range=(2, 2)得到如下结果,稍稍优于3-Gram。

vld检测不输出_原创干货 | 基于机器学习的webshell检测踩坑小记相关推荐

  1. 基于机器学习的webshell检测(一)

    本篇主要讲述,如何使用机器学习的方法来对网络安全中常见的风险点:webshell进行检测 本篇会使用LR ,XGB两种模型进行测试, 下一篇将会使用深度学习方法来解决该问题 (1)首先我们简单介绍一下 ...

  2. [当人工智能遇上安全] 6.基于机器学习的入侵检测和攻击识别——以KDD CUP99数据集为例

    您或许知道,作者后续分享网络安全的文章会越来越少.但如果您想学习人工智能和安全结合的应用,您就有福利了,作者将重新打造一个<当人工智能遇上安全>系列博客,详细介绍人工智能与安全相关的论文. ...

  3. 二十四.基于机器学习的入侵检测和攻击识别——以KDD CUP99数据集为例

    这是作者的系列网络安全自学教程,主要是关于网安工具和实践操作的在线笔记,特分享出来与博友共勉,希望您们喜欢,一起进步.前文分享了Web渗透的第一步工作,涉及网站信息.域名信息.端口信息.敏感信息及指纹 ...

  4. 卡巴斯基白皮书-基于机器学习的恶意软件检测-笔记

    前言:下文用"我们"表示卡巴斯基实验室,(?)标记尚有疑问处.原文地址.这篇文章描述卡巴斯基实验室基于机器学习的恶意软件检测实践,包括静态分析和行为分析两类检测方法,以及数据预处理 ...

  5. [网络安全自学篇] 二十四.基于机器学习的入侵检测和攻击识别——以KDD CUP99数据集为例

    这是作者的系列网络安全自学教程,主要是关于网安工具和实践操作的在线笔记,特分享出来与博友共勉,希望您们喜欢,一起进步.前文分享了Web渗透的第一步工作,涉及网站信息.域名信息.端口信息.敏感信息及指纹 ...

  6. GitChat · 安全 | 基于机器学习的 Webshell 发现技术探索

    GitChat 作者:兜哥 原文: 基于机器学习的 Webshell 发现技术探索 关注公众号:GitChat 技术杂谈,一本正经的讲技术 第十一章WebShell检测 WebShell就是以ASP. ...

  7. 基于dx11的动作游戏踩坑之路--1

    基于dx11的动作游戏踩坑之路--1 首先要声明所有的博客都是学习博客,不是技术博,只是用来记录.整理自己的学习路线,以及日后可以回顾一下.本人也只是一个小菜鸡,可能会有很多错误与纰漏,有大佬愿意指出 ...

  8. vld检测不输出_专业分享丨高频电刀的质量控制检测

    作  者:梁世波,邓文涛 单  位:右江民族医学院附属医院医疗设备科 (广西百色 533000) 来  源:<医疗装备>杂志2020年第15期 [摘 要]高频电刀是一种被广泛应用于医疗实践 ...

  9. 基于python的智能文本分析 豆瓣_长文干货 | 基于豆瓣影评数据的完整文本分析!...

    原标题:长文干货 | 基于豆瓣影评数据的完整文本分析! 作者:沂水寒城,CSDN博客专家,个人研究方向:机器学习.深度学习.NLP.CV Blog: http://yishuihancheng.blo ...

  10. 【目标检测_keypoint based 方法系列】基于关键点的目标检测

    文章目录 一.CornerNet 二.ExtremeNet 三.CenterNet 3.1 关键步骤: 3.2 关键点检测网络: 3.3 目标大小的回归 3.4 从点到b-box: 3.5 Cente ...

最新文章

  1. matlab矩阵乘法与打印
  2. C语言树形打印二叉树
  3. swoole 定时器
  4. VB课本基础知识总结
  5. 使用AutoMake轻松生成Makefile
  6. mysql连接超时timeout问题
  7. 你好,面试官 | 你拿Java Map考验老干部?
  8. 使用phyton脚本产生新的mac地址
  9. Linux下PhpMyAdmin程序目录的安全管理
  10. jsp嵌入vlc视频回放_【知识】如何用监控进行视频直播?一文了解清楚
  11. 阿里云服务器学生计划--免费领取两个月
  12. 如何让html 兼容IE和chrome,chrome兼容模式如何切换成IE兼容模式_chrome兼容模式切换成IE兼容模式的方法-系统城...
  13. 目前常用的室内导航地图有哪些?什么软件可以室内导航?
  14. vs2010中正确加载gif格式图片
  15. 20组免费的Photoshop渐变效果素材
  16. 请帮我写一封情书,500字左右
  17. .net 2.0安装包打不开_Android——bilibili缓存视频合并教程[2.0]
  18. 笔记本触摸板驱动,让你完全抛弃鼠标
  19. 【攻破html系列——第四天】图片标签和超链接
  20. AutoCAD 2008中文版标准教程(第2版)

热门文章

  1. 嵌入式硬件入门——74HC138译码器(三个IO实现8选1)
  2. 74HC138译码器的原理和使用
  3. 2021年道路运输企业主要负责人和安全生产管理人员安全考核题型[安考星]
  4. [高效Mac] 多显示器快速切换鼠标焦点和移动窗口
  5. IPFS是创建DWeb应用程序中基础技术的领先者
  6. 2001年新闻组大全
  7. python处理地震sac数据_[数据处理] 地震数据及相关软件概述
  8. ADSL 错误691
  9. 计算机轻量级硬件性能测试软件推荐
  10. 计算机测试性评估,计算机CPU性能评估软件PCMark