loader image

Python mod_security(WAF)の統計情報を分かりやすく出力する

import sys
import re

file_path = '/home/centos/abe/guard/modsec_audit.log'

def main():

    # read log
    log_list = read_log()

    # exec_type_list
    summary_type_list = sys.argv[1].split(',')
    summary_type_list = list(set(summary_type_list))

    for summary_type in summary_type_list:
        eval('{0}_{1}'.format('summary_type', summary_type))(log_list)

## summary_type
def summary_type_1(log_list): # id
    column = 'id,count'
    id_dict = {}

    # Message
    message_list = get_param_list(log_list, 'Message')
    for message in message_list:
        item_list = get_value(message)
        item = get_item(item_list, 'id')
        dict_count(id_dict, item)

    print_dict(id_dict, column)

def summary_type_2(log_list): # client
    column = 'client,count'
    client_dict = {}

    # Apache-Error
    apache_error_list = get_param_list(log_list, 'Apache-Error')
    for apache_error in apache_error_list:
        item_list = get_value(apache_error)
        item = get_item(item_list, 'client')
        dict_count(client_dict, item)

    print_dict(client_dict, column)

def summary_type_3(log_list): # action
    column = 'action,count'
    action_dict = {}

    # Action
    action_list = get_param_list(log_list, 'Action')
    action_list = split_value(action_list)

    for item in action_list:
        dict_count(action_dict, item)

    print_dict(action_dict, column)

def summary_type_4(log_list): # hour
    column = 'hour,count'
    hour_dict = {}

    # hour
    request_list = get_param_list(log_list, '[')
    for request in request_list:
        item = get_value(request, start=':', end=':')[0]
        dict_count(hour_dict, item)

    print_dict(hour_dict, column)

## function
def read_log():
    log_list = []

    with open(file_path) as f:
        raw_list = f.readlines()

    tmp_list = []
    write_flag = False
    for raw in raw_list:
        raw = raw.replace( '\n', '' )
        if raw.endswith('A--'):
            write_flag = True
        if raw.endswith('Z--'):
            write_flag = False
            if check_raw_list(tmp_list):
                log_list = log_list + tmp_list
            tmp_list = []

        if write_flag and not raw.startswith('--'):
            tmp_list.append(raw)

    return log_list

def check_raw_list(tmp_list):
    for tmp in tmp_list:
        if tmp.startswith('Message'):
            return True
    return False

def print_dict(target_dict, column):
    stdout(column)
    for k, v in sorted(target_dict.items(), key=lambda x: -x[1]):
        stdout(str(k) + ": " + str(v))

def dict_count(target_dict, item):
    if not item in target_dict:
        target_dict[item] = 0
    target_dict[item] = target_dict[item] + 1

def get_item(target_list, param_name):
    for target in target_list:
        ret = target.split(' ')
        if ret[0] == param_name:
            return ret[1].replace( '"', '' )

def get_param_list(log_list, start_str):
    ret = []
    for log in log_list:
        if log.startswith(start_str):
            ret.append(log)
    return ret

def split_value(target_list):
    ret = []
    for target in target_list:
        ret.append(target.split(': ')[1].replace( '\n', '' ))
    return ret

def get_value(line, start='\[', end='\]'):
    p = r'{0}(.+?){1}'.format(start, end)
    items = re.findall(p, line)
    return items

# util
def stdout(str):
    print(str)

## main
if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        stdout(e)

コメント

タイトルとURLをコピーしました