使用LOF(Local Outlier Factor)异常检测算法检测异常访问者

 在日常日志分析中,我们通常使用自己的“安全经验”编写出关于攻击的一些规则去寻找日志中攻击行为,从而得到一段时间内的异常访问者IP,即所有“命中过规则”的访问者,而面对千变万化的Web应用、不断更新迭代的技术以及攻击者变幻莫测的攻击手法,难免我们有时无法紧随攻击者的步伐,如果某一个攻击者发起过攻击但是所使用的攻击手法不在我们所已知的安全经验范围内,此时这个恶意的访问者便会从我们的关注范围溜走。
     此时我们可以另辟蹊径,忘掉那些已知的安全规则,尝试使用不同的方法在日志中找到异常访问者。此时我们可以使用异常检测算法中的LOF算法(Local Outlier Factor).算法的基础理论是通过计算数据之间距离,通过距离可计算每个对象的可达密度,然后计算出数据点是否在一个数据相对密集的区,称为局部异常因子。关于算法详细的原理可以自行参考[论文](http://www.dbs.ifi.lmu.de/Publikationen/Papers/LOF.pdf)和查询相关资料。我们暂且将LOF算法作为一个黑箱使用,下面记录实践过程:
    
   一、数据准备
       第一个环节我们需要准备相关的数据,数据的质量、准确度会直接影响算法计算的结果。关于日志相关的基础知识可以参考我的[另外一篇文章](https://jeary.org/post-76.html)。这一步我们可以简单思考日志中的哪些信息对“异常因素”的影响比较大。简单说就是:“从日志数据中观察,一个访问者满足哪些条件会让我们觉得算是异常?”这里个人简单列举一些:
       1.访问量大于90%以上的访问者(请求包过多,扫描和爬虫可能性大)
       2.响应大小大于90%以上的访问者(访问大文件过多,存在脱数据、爬数据嫌疑)
       3.状态码分布范围(状态码多样化,普通人应该只有少数几个,如200、301、302、404,而攻击者会尝试各类的攻击,访问需要授权的页面会在日志中产生401、403,一些页面由于未处理错误会导致接收到特殊字符时在页面产生500状态码)
       4.访问频率过快(正常访问者不可能短时间并发成百上千的请求)
       5.请求方式分布(正常用户应该大部分都是GET\POST请求,而异常访问者则会有大量其他方式的请求)
       6...(暂且列举这么多,其实像客户端信息、访问者请求长度分布、请求页面分布、请求时间分布等等都可以经过计算、预处理以后作为计算数据)
       

       数据收集完毕,示例数据大概长这个样子:

点击查看原图


 数据中每一行为一个访问者的基础属性,分别对应请求量、请求频率、响应总流量(mb)、常用15个状态码分布情况、请求方式分布请求,对应的实体对象如下图:

点击查看原图

 PS:本文中得数据是通过使用ElasticSearch聚合搜索并通过预处理整理得出,如果你只是为了测试算法,可自习通过自己认为简单方便的方法。
 
  二、算法测试
              数据准备好后,我们需要找到LOF算法的库并实际测试。由于数据是通过Java连接ElasticSearch获取的,但是Java中并没有像Python那样丰富的机器学习算法库(还是Python大法好),于是本来通过Java获取数据,然后通过Python进行算法计算,不过在这之前上Github中搜索了一番,找到算法爱好者实现了[Java版的LOF](https://github.com/wilsonact/LOF-java),部署好项目之后,运行其中的测试案例查看效果:

点击查看原图

根据算法原理LOF得分和1相差越大,则越表明数据点为异常点。
              
 
  三、    实际测试
         测试代码运行成功后,我们需要将真实数据构造并传入算法中进行计算,

点击查看原图

点击查看原图

 实际测试效果让人有点疑惑,因为得分最高的人看上去并不是“最异常“的访问者,可能是大量的占位数据会对LOF算法产生影响,也有可能是因为在同一行数据中有相同的数据导致,想要弄清楚其中的原因,有两种办法。
              1.深究算法内部原理,推导算法计算过程
                      时间成本:大
                      学习价值:高
                      实现难度:高
              2.算法黑盒测试,通过更改数据维度,少量数据进行测试并观察结果
                      时间成本:中
                      学习价值:一般
                      实现难度:低
  由于本次目的是为了通过算法实现如何找出异常访问者,而并非LOF算法学习,所以我们果断选择方案二。
 
四、算法修正
        由于结果并不是我们想要的,所以做的第一次尝试是减少数据维度,

点击查看原图

未完待续..


发表评论