1. 程式人生 > >我的日誌分析之道:簡單的Web日誌分析指令碼

我的日誌分析之道:簡單的Web日誌分析指令碼

前言

長話短說,事情的起因是這樣的,由於工作原因需要分析網站日誌,伺服器是windows,iis日誌,在網上找了找,github找了找,居然沒找到,看來只有自己動手豐衣足食。

那麼分析方法我大致可分為三種:

1. 基於時間:將請求url按時間段分類,那麼我們根據每個時間段的url數量及攻擊數量就可以大致判斷出哪個時間段有apt型別攻擊,哪個時間段是掃描器行為;

2. 基於攻擊ip:正常的攻擊肯定會有請求被記錄(當然你要是有0day當我沒說,正常的探測總會有吧=。=!),然後每個ip去分析;

3. 基於訪問請求的狀態碼,也大致可以判斷出行為。

規則可以基於開源waf規則,分析掃描器寫正則也可以,開源waf地址是

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來弄成圖形化,畢竟指令碼始終是指令碼,終究聽著不好聽。

效果如下

具體規則有待完善。