草庐IT

机器学习之KNN检测恶意流量

小黑安全 2023-04-03 原文

背景

任何智能活动的都可以称为人工智能,而机器学习(Machine Learning)属于人工智能的一个分支,深度学习(Deep Learning)则是机器学习的分支。近年来,随着基础设施的完善,海量大数据的积累,机器学习方法理论越来越成熟,算力的大幅度提升,互联网企业也越来越愿意增大在AI领域的投入,AI的优势在于处理海量数据提取捕获其中有用信息上发挥着非常重要的作用,如OCR领域图片鉴黄、自然语言处理方面的恶意言论捕获、风控领域画像、推荐系统等。

概念

目的
通过机器学习的方式识别恶意流量

特征工程
使用sklearn的TFIDF、2ngram进行分词

什么是TF-IDF

TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。如果某个单词在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。

词频(TF) = 某个词在文章中的出现次数

逆文档频率(IDF) = log(语料库的文档总数/包含该词的文档总数+1)

公式:TF-IDF = TF * IDF

举例:假设一篇文章中由1万个词组成,其中“跨站脚本”,“web”,“安全”,“攻击”几个词各出现100次,那么他们对应的词频TF就是 TF = 100/10000 = 0.01。

语料库中一共有1000篇文章,其中包含“跨站脚本”的有9篇,包含“web”的有89篇,包含“安全”的有399篇,包含“攻击”的有499篇,那他们对应的TDF如下,由TFIDF值可知这篇文章重点应该是在讲“跨站脚本”

流程
数据集正例样本10万,数据集负例样本5万,由于初始负例样本不足,可以在特征工程阶段将负例样本*2扩大负例样本的数据集数量,但效果不会很明显,一般在深度学习的时候特征样本不足我会这样做数据扩展。

对数据做一些基础的特征工程对连续的数字或单独的数字都转化为’8’,将quries里的https|http转化成同一个特征量等等

label 0 标记正例样本,label 1 标记负例样本

class LR(object):
def init(self):

self.goodX = self.DecodeQuery(“./goodX.txt”)
self.badX = self.DecodeQuery(“./badqX.txt”)
self.goodY = [0] * len(self.goodX)
self.badY = [1] * len(self.badX)
self.vectorizer = TfidfVectorizer(ngram_range=(1, 3))
self.X = self.vectorizer.fit_transform(self.goodX + self.badX)

1.def DecodeQuery(self, fileName):    data = [x.strip() for x in open(fileName, "r").readlines()]    query_list = []    for item in data:        item = item.lower()        if len(item) > 50 or len(item) < 5:            continue                h = HTMLParser()        item = h.unescape(item)        item = parse.unquote(item)        item, number = re.subn(r'\d+', "8", item)        item, number = re.subn(r'(http|https)://[a-zA-Z0-9\.@&/#!#\?:]+', "http://u", item)        query_list.append(item)    return list(set(query_list))

模型训练与预测

train_test_split函数用于将矩阵随机划分为训练子集和测试子集,并返回划分好的训练集测试集样本和训练集测试集标签,其中test_size是代表要划分出多少的数据做为测试集,random_state是种子,也就是说当random_state不为0时,每次train_test_split生成的数据集是一致的,以便与我们在初期阶段保持数据集一致进行调试。

模型使用KNN(K-Nearest neigbour,KNN)Cover和Hart在1968年提出了最初的邻近算法。所谓KNN,就是K个最近邻居的意思。说的是每个样本都可以用它最接近的k个邻居来代表。属于一种有监督的分类(Classification)算法,同时属于懒惰学习(lazy learning)即KNN没有显式的学习过程,也就是没有训练数据的阶段,所以也代表了该阶段的时间开销为零,数据集事先已有了分类和特征值,待收到新样本后直接进行处理。

KNN三要素

1.K值的选择:对于K值的选择,如果K值较小表示使用较小邻域中的样本进行预测,训练误差会减少,但是模型会变得复杂,容易过拟合。

2.距离的度量:一般使用欧几里得距离

3.决策规则:分类模型中使用多数表决的方式或者加权表决(距离与权重成反比);在回归模型中,使用平均值法

KNN的优化

当如果有大量的数据输入的时候为了加快检索,引入了优化算法,相当于是使用了特殊的结构来保存数据,以减少数据的检索次数。

KNN的使用

def TrainModel(self):

    X_train, X_test, y_train, y_test = train_test_split(self.X, self.goodY + self.badY, test_size=0.2, random_state=16)

    knn = neibours.KNeiborsClassifier(n_neibours=5)

    knn.fit(X_train, y_train)

    joblib.dump(knn, "knn.pickle")

在做模型训练的时候,尤其是在训练集上做交叉验证,通常想要将模型保存下来,然后放到独立的测试集上测试,scikit-learn已经有了模型持久化的操作,存储模型(持久化)一般就两种方式一种是joblib和pickle

倒入模块 from sklearn.externals import joblib

保存模型 joblib.dump(model,’filename.pkl’)

读取模型 joblib.load(modelName)

def Predicts(self, modelName, fileName):

    knn = joblib.load(modelName)

    input_x = self.DecodeQuery(fileName)

    X_predict = self.vectorizer.transform(input_x)

    res = knn.predict(X_predict)

    res_list = []        for url , y in zip(input_x, res):

        label = '正常请求' if y == 0 else '恶意请求'

        print(label , url )

最终预测结果

这里算法笔者用的KNN,但KNN属于懒惰算法,最大但缺点之一在于在数据量庞大的时候运算会非常的慢,另外一个会受离群点的影响,这个knn的例子只适合做试验讲解,因为KNN具有良好的可解释性上

1.恶意请求 /cgi-home/ion-p?page=../../../../../etc/passwd

2.恶意请求 <svg><script xlink:href=data:,alert(8) />

3.恶意请求 /./\/././\/././\/././\/././\/././\/././\/./{file}

4.正常请求 /scripts_photositeprinting/正常请求 /main.php?stuff="&ver&rem\xa8

总结

机器学习比较痛苦的是调参数、做特征工程,本文没有特意去做特征工程使用了ngram分词实现的特征,调参的话懒人可以通过GridSearch和RandomizedSearchCV进行搜索

有关机器学习之KNN检测恶意流量的更多相关文章

  1. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  2. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  3. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  4. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  5. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  6. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  7. ruby - 我正在学习编程并选择了 Ruby。我应该升级到 Ruby 1.9 吗? - 2

    我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or

  8. ruby-on-rails - Ruby 流量控制 : throw an exception, 返回 nil 还是让它失败? - 2

    我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id

  9. ruby - 检测由 RSpec、Ruby 运行的代码 - 2

    我想知道我的代码是否在rspec下运行。这可能吗?原因是我正在加载一些错误记录器,这些记录器在测试期间会被故意错误(expect{x}.toraise_error)弄得乱七八糟。我查看了我的ENV变量,没有(明显的)测试环境变量的迹象。 最佳答案 在spec_helper.rb的开头添加:ENV['RACK_ENV']='test'现在您可以在代码中检查RACK_ENV是否经过测试。 关于ruby-检测由RSpec、Ruby运行的代码,我们在StackOverflow上找到一个类似的问题

  10. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

随机推荐