我的日志分析之道 | 简单的Web日志分析脚本

前言

长话短说,事情的起因是这样的,由于工作原因需要分析网站日志,服务器是windows,iis日志,在网上找了找,github找了找,居然没找到,看来只有自己动手丰衣足食。

那么分析方法我大致可分为三种:

1. 基于时间:将请求url按时间段分类,那么我们根据每个时间段的url数量及攻击数量就可以大致判断出哪个时间段有apt类型攻击,哪个时间段是扫描器行为;

2. 基于攻击ip:正常的攻击肯定会有请求被记录(当然你要是有0day当我没说,正常的探测总会有吧=。=!),然后每个ip去分析;

3. 基于访问请求的状态码,也大致可以判断出行为。

规则可以基于开源waf规则,分析扫描器写正则也可以,开源waf地址是

https://github.com/loveshell/ngx_lua_waf/tree/master/wafconf。

扫描器正则https://github.com/smarttang/w3a_SOCD的database里面有详细地址

https://github.com/smarttang/w3a_SOC/tree/master/db_sql。

Sql语句里面有想把它做的功能全一些,但是学python学习时间也不是很长,写出来的代码也没有pythonic,会慢慢写的。

目前分三个模块,一个日志归类模块命名为url.py,攻击分析模块attac.py, ip地理位置查询模块ipfind.py,还有一个主函数。

日志归类模块url.py

import re import os import sys from datetime import datetime dt = datetime.now() date = str(dt.date()) loglist = [] # iplist = [] # ip统计 urllist = [] # url统计列表 needlist = [] # 需要统计的 errorlist = [] # 格式错误的列表 ipdict,urldict = {},{} rizhi = str(input('请输入要分析的日志文件名')) def find_log(): print('>>>>>>>开始解析日志') with open(rizhi,'r',encoding='UTF-8',errors='ignore') as f: #loglist = f.readlines() for i in f.readlines(): # if i[0] != '#': b = re.split(' ',i) iplist.append(b[10]) urllist.append(b[6]) try: needlist.append([b[10],b[1],b[5],b[6],b[15]]) except: errorlist.append(i) print('>>>>>>>日志解析完毕') def count(iplist,urllist): #统计ip url访问量函数 print('>>>>>>>开始分析url与ip访问量') global ipdict,urldict for i in set(iplist): ipdict[i] = iplist.count(i) for i in set(urllist): urldict[i] = urllist.count(i) ipdict = sorted(ipdict.items(),key=lambda d: d[1], reverse=True) urldict = sorted(urldict.items(),key=lambda d: d[1], reverse=True) print(type(urldict)) iplist = list(ipdict) urllist = list(urldict) ipdict,urldict = {},{} print('>>>>>url与ip分析完毕.......') return [iplist,urllist] def save_count(): print('>>>>>>>正在保存分析结果') ipname = 'ip-'+date+'.txt' urlname = 'url-'+date+'.txt' with open(ipname,'w') as f: for i in iplist: f.write(str(list(i))+'\n') with open(urlname,'w') as f: for i in urllist: f.write(str(list(i))+'\n') print('>>>>>>>分析结果保存完毕') find_log() [iplist,urllist] = count(iplist,urllist) save_count()

iis日志和apache日志觉得都差不多,就是切割时候改一下就行了。

Iis日志大概是这样的,用pythonreadlines然后切割出来就好了。

这个url.py我加了个功能把ip访问量及url访问量排序输出出来所以有点慢,=.=没办法野路子哪里会什么算法。将地址,时间,ip,状态码都扔进一个列表里就行了。

攻击分析模块attack.py

import os import sys import url sqllist,xsslist,senlist = [],[],[] otherurl,xssip,sqlip,senip = [],[],[],[] feifa = [] def find_attack(needlist): print('>>>>>>>开始检测攻击') sql = r'product.php|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|^eval$|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|\(?:define|base64_decode\(|group\s+by.+\(|%20or%20|%20and%20|sleep|delay|nvarchar|exec|union|^select$|version|insert|information_schema|chr\(|concat|%bf|sleep\((\s*)(\d*)(\s*)\)|current|having|database' xss = r'alert|^script$|<|>|%3E|%3c|&#x3E|\u003c|\u003e|&#x' sen = r'\.{2,}|%2e{2,}|%252e{2,}|%uff0e{2,}0x2e{2,}|\./|\{FILE\}|%00+|json|\.shtml|\.pl|\.sh|\.do|\.action|zabbix|phpinfo|/var/|/opt/|/local/|/etc|/apache/|\.log|invest\b|\.xml|apple-touch-icon-152x152|\.zip|\.rar|\.asp\b|\.php|\.bak|\.tar\.gz|\bphpmyadmin\b|admin|\.exe|\.7z|\.zip|\battachments\b|\bupimg\b|uploadfiles|templets|template|data\b|forumdata|includes|cache|jmxinvokerservlet|vhost|bbs|host|wwwroot|\bsite\b|root|hytop|flashfxp|bak|old|mdb|sql|backup|^java$|class' for i in needlist: if i[2] == 'POST' or i[2] == 'HEAD' or i[2] == 'GET': response = re.findall(sql,i[3],re.I) if response == []: responsexss = re.findall(xss,i[3],re.I) if responsexss == []: responsesen = re.findall(sen,i[3],re.I) if responsesen == []: otherurl.append(i) else: senlist.append(i) senip.append(i[0]) print(responsesen) print('检测出敏感目录扫描') print(i) else: xsslist.append(i) xssip.append(i[0]) print(responsexss) print('检测出xss攻击') print(i) else: sqllist.append(i) sqlip.append(i[0]) print(responsexss) print('检测出sql攻击') print(i) else: feifa.append(i[0]) print('非法请求:'+str(len(feifa))+'次'+str(len(list(set(feifa))))+'个ip') print('>>>>>>>攻击检测完毕') return [xssip,sqlip,senip,sqllist,xsslist,senlist,otherurl]

这个就简单多了,基于正则分析的正则不是很完善,还有好多是根据自己公司情况来定,大牛轻喷,检索完毕返回ip及url。

IP地理位置查询模块ipfind.py

Ipfind.py是查找ip地理位置的

import re import urllib.request def url_open(ip): url = 'http://www.ip138.com/ips138.asp?ip='+ip response = urllib.request.urlopen(url) html = response.read().decode('gb2312') return html def find_ip(html): a = r'本站数据.{20,}</li>' p = re.compile(a,re.I) response = re.findall(p,html) for i in response: b = i response = re.split(r'</li><li>',b) ipaddrs = str(response[0][5:])+','+str(response[1][6:])+','+str(response[2][6:-5]) return ipaddrs def find_ipaddrs(ip): html = url_open(ip) ipaddrs = find_ip(html) print(ip+' : '+ipaddrs)

这个简单我是直接像爬虫那样写的,用ip138的网址(接口没有找到,百度注册了好几次都不成功,有api的可以用api)。

主函数

主函数main.py

import re import os import sys from datetime import datetime import url import attack import ipfind needlist = url.needlist sqllist,xsslist,senlist = [],[],[] otherurl,iplist = [],[] [xssip,sqlip,senip,sqllist,xsslist,senlist,otherurl]=attack.find_attack(needlist) xssip = list(set(xssip)) sqlip = list(set(sqlip)) senip = list(set(senip)) print('>>>>>>>检测出xss攻击'+str(len(xsslist))+'次'+'共计'+str(len(xssip))+'个ip') print(xssip) print('>>>>>>>检测出sql攻击'+str(len(sqllist))+'次'+'共计'+str(len(sqlip))+'个ip') print(sqlip) print('>>>>>>>检测出敏感目录扫描'+str(len(senlist))+'次'+'共计'+str(len(senip))+'个ip') print(senip) iplist = list(set(xssip+sqlip+senip)) print(len(iplist)) print('开始分析ip地理位置') for i in iplist: ipfind.find_ipaddrs(str(i))

要分析什么就把需要分析的和main.py放在一个目录下就行了

总结

脚本大概说了一遍,说说不足及怎么分析吧。

现实不足:看了差不多有3个月日志了吧,先说一个最严重的问题,post请求data看不见,本身日志就看不到data,何况等到https普及了日志什么样也不知道,要是有能力最好做成和waf联动那样的。

还有就是未知威胁从waf来看基于正则,基于关键词有很多都是能绕过的,但是有攻击行为没删日志的话,肯定是会留下攻击痕迹的,这样可以从检测出来的ip来看具体攻击的url。

而未知威胁则不同了,就好比一个0day,攻击waf没用了,日志分析看不出来了,那么只能依靠应急响应以及服务器的报警了。

还有好多攻击类型没有加入到里面,后期打算把判断攻击类型写成函数,拿if,else判断,类型少还可以,类型多了感觉很容易乱,还有user-agent的收集与判断(虽然大多数扫描器都能改user-agent)。

具体分析:我都是用脚本跑一遍,然后按ip来看会比较方便些,而这里缺少机器识别,我单独写了一个简易的机器识别的东西,其实要实现很简单,把全部日志按时间,url,ip扔进一个列表里统计一下相同时间相同ip的就可以了。

我写的是识别短信轰炸的,后期还会渐渐的完善,如果有能力就把它结合django来弄成图形化,毕竟脚本始终是脚本,终究听着不好听。

效果如下

具体规则有待完善。

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2017-02-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏双十二技术哥

组件化实践详解(一)

具体实施一项技术项目之前我们会首先确定对应的目标,之后的行动计划都会朝着目标一步步靠拢。

662
来自专栏me的随笔

Visual Studio 代码风格约束

注意,这里的错误是IDE1006:Naming rule violation,编译时依然能通过(没找到在哪里设置不允许通过编译):

1762
来自专栏Golang语言社区

高效网游服务器实现探讨 - jack-wang - C++博客

高效网游服务器实现探讨 随着多核处理器的普及,如何充分利用多核并行工作就成为高性能程序设计的一个重点。本系列文章将围绕高性能网游服务器的实现,探讨这方面的技术。...

38111
来自专栏做全栈攻城狮

程序员带你学习安卓开发,十天快速入门-基础知识(四)

我们就是通过测试项目进行学习安卓基本语法。展开之后,打开ExampleUnitTest类。

905
来自专栏腾讯开源的专栏

手游热更新方案xLua开源:Unity3D下Lua编程解决方案

xLua是Unity3D下Lua编程解决方案,自2016年初推广以来,已经应用于十多款腾讯自研游戏,凭借其出色的性能,易用性,扩展性而广受好评。现在xLua开源...

7196
来自专栏java一日一条

改善Java文档的理由、建议和技巧

我非常确定,作为开发人员我们都喜爱技术文档。我们喜欢阅读文档、写文档,更不用说维护文档了,我简直爱死它了!

481
来自专栏王清培的专栏

数据分表小结

本次拆分主要包括订单和优惠券两大块,这两块都是覆盖全集团所有分子公司所有业务线。随着公司的业务飞速发展,不管是存储的要求,还是写入、读取的性都基本上到了警戒水位...

990
来自专栏芋道源码1024

Dubbo 源码解析 —— Cluster

前言 今天是小长假的倒数第二天,本来国庆是要加班四天的,后来因为要有事要回家才得以幸免,但是后天上班之后都要搬砖搬到手脱皮是必须的了.但是再忙每周一篇源码解析...

3645
来自专栏炉边夜话

免费的午餐已经结束,你准备好了吗?

2005年3月,C++大师Herb Sutter在Dr.Dobb’s Journal上发表了一篇名为《免费的午餐已经结束》的文章,一石激起千层浪,该文引起了社区...

862
来自专栏竹清助手

现代化PHP开发

PHP 正在重生。作为一门专注WEB开发的语言,它不断吸取其他语言的优点,如命名空间,闭包,性状,操作码缓存等特性,PSR 规范和Composer 包管理以及...

1962

扫码关注云+社区

领取腾讯云代金券