贴一篇自己写的PYTHON实现LINUX入侵检测脚本

发布于 2023-06-15  312 次阅读


  • 脚本通过正则和文件读写操作,统计linux安全日志文件中记录的登录失败的ip,登录失败次数,试图登录使用过的用户名和登录操作的时间,并生成了excel表格

安全日志

  • 分析脚本利用了/var/log/secure文件,它一般用来记录安全相关的信息,记录最多的是哪些用户登录服务器的相关日志
Dec 27 14:04:51 139 sshd[30956]: Disconnecting: Too many authentication failures [preauth]
Dec 27 14:04:53 139 sshd[30968]: Invalid user user from 193.201.224.12 port 26133
Dec 27 14:04:53 139 sshd[30968]: input_userauth_request: invalid user user [preauth]
Dec 27 14:05:01 139 sshd[30968]: Disconnecting: Change of username or service not allowed: (user,ssh-connection) -> (User,ssh-connection) [preauth]
Dec 27 14:05:03 139 sshd[30996]: Invalid user User from 193.201.224.12 port 43273
  • 常见信息解释
Jan 17 12:27:36 139 sshd[12812]: pam_unix(sshd:session): session closed for user root 
# 表示root用户关闭了会话(也就是关闭了终端)

Jan 17 12:28:59 139 sshd[14064]: Accepted publickey for root from 14.23.168.10 port 36637 ssh2 
# 表示接受来自14.23.168.10的root用户的公钥登录

Jan 17 12:28:59 139 sshd[14064]: pam_unix(sshd:session): session opened for user root by (uid=0) 
# 表示给root用户打开一个终端

Jan 17 14:41:10 Mir2_Center sshd[9913]: Received disconnect from 183.60.122.237: 11: disconnected by user 
# 表示已经连着的终端主动断开连接,并关闭终端

Jan 17 14:39:48 139 sshd[31261]: Invalid user redis from 45.115.45.3 port 33274 
# 表示对端使用无效的用户redis来连接

Jan 17 14:39:48 139 sshd[31261]: input_userauth_request: invalid user redis [preauth] 
# 本机对redis用户进行认证,认证失败,发送错误信号给对端

Jan 17 14:39:48 139 sshd[31261]: Received disconnect from 45.115.45.3 port 33274:11: Bye Bye [preauth] 
# 对端接收到错误信号主动断开连接

Jan 17 14:39:48 139 sshd[31261]: Disconnected from 45.115.45.3 port 33274 [preauth] 
# 连接关闭

xlwt库

  • xlwt库用来生成excel,其基本用法为
import xlwt

# 1.创建 Workbook
wb = xlwt.Workbook()

# 2.创建 worksheet
ws = wb.add_sheet('test_sheet')

# 3.写入第一行内容  ws.write(a, b, c)  a:行,b:列,c:内容
ws.write(0, 0, '球队')
ws.write(0, 1, '号码')
ws.write(0, 2, '姓名')
ws.write(0, 3, '位置')

# 保存文件
wb.save('./myExcel.xls')

pandas库

  • 这里只用来pandas库的统计功能,temp是数组,按以下操作处理后可以实现数组元素排序,并统计出现次数,次数与元素内容用*间隔
result=pd.value_counts(temp)
result.to_csv('ip.txt', sep='*')
#得到
x.x.x.x*671 x.x.x.x出现671次
z.z.z.z*633 z.z.z.z出现633次

数组去重

  • 直接用set函数
num = [1,2,1,4,5]
print(list(set(num)))
#得到
[1, 2, 4, 5]

脚本

  • 只需将linux的/var/log/secure文件cv一份命名为original放在脚本同目录下,即可在脚本目录下得到result.xlsx.小白练手,写的很丑🥺
import re
import pandas as pd
import time
import os
import numpy as np
import xlrd
import xlwt

def find1(pattern,input_string):
    pattern = pattern
    input_string=input_string
    match = re.search(pattern, input_string, re.DOTALL)
    if match:
        return match.groups()
    else:
        return None

def find(pattern,input_string):
    pattern = pattern
    input_string=input_string
    match = re.search(pattern, input_string, re.DOTALL)
    if match:
        return match.group(1)
    else:
        return None

def findall(pattern,input_string):
    pattern = pattern
    matches = re.findall(pattern, input_string,re.MULTILINE)
    return matches

def is_line_without_english(line):
    # 使用正则表达式匹配字母
    pattern = r'[a-zA-Z]'
    match = re.search(pattern, line)

    # 如果没有匹配到字母,则表示该行没有英文
    if match:
        return False
    else:
        return True

def has_substring(string, substring):
    if string.find(substring) != -1:
        return True
    else:
        return False

def get_first_word(string):
    words = string.split(" ")
    if len(words) > 0:
        return words[0]
    else:
        return ""

if(os.path.exists('result.xls')):
    print("存在同名文件占用,请手动删除同目录下的result.xls后重启程序")
    time.sleep(10000)
print("程序在5秒后将会启动,请确保original(分析文件)与程序在同一目录下")
time.sleep(5)
print("正在统计访问ip")
original = open("original")
original_txt = original.read()
temp=findall(r'rhost=([\d.]+)',original_txt)
original.close()
result=pd.value_counts(temp)
result.to_csv('ip.txt', sep='*')

original = open("original")
original_txt = original.read()
temp=findall(r'Failed password for invalid user (.*?) port',original_txt)
original.close()
user=pd.value_counts(temp)
user.to_csv('user.txt', sep='\t')
print("正在统计访问用户")

ip = open("ip.txt")
ip_txt = ip.readlines()
user = open("user.txt")
user_txt = user.readlines()
u=1
i=1
with open('result.txt', 'w') as f:
    for iline in ip_txt:
        #print(iline)
        if(i==1):
            i=i+1
            continue
        i=i+1
        #print(uline)
        iip=find1(r'(?<![\.\d])(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])(?![\.\d])',iline)
        #print(uline)
        upan=0
        for uline in user_txt:
            if(u==1):
                u=u+1
                continue
            u=u+1
            uip=find1(r'(?<![\.\d])(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])(?![\.\d])',uline)
            if(uip==iip):
                if(has_substring(iline,get_first_word(uline.replace("\n",'')).replace("\n",''))==False):
                    if(upan==0):
                        iline=iline.replace("\n",'')+"*"+get_first_word(uline.replace("\n",'')).replace("\n",'')+"\n"
                        upan=upan+1
                    else:
                        iline=iline.replace("\n",'')+","+get_first_word(uline.replace("\n",'')).replace("\n",'')+"\n"
                        upan=upan+1
        if(upan==0):
            iline=iline.replace("\n",'')+" *"+"\n"
            print(iline)
        f.write(iline)          
f.close()
print("正在统计访问时间")
original = open("original")
original_txt = original.readlines()
with open('time.txt', 'w') as f:
    for line in original_txt:
        if(has_substring(line,"Failed password")):
            ip_temp=find(r'from (.*?) port ',line)
            time_temp=re.search(r"^(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", line, re.DOTALL).group(1)+" "+re.search(r"^(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", line, re.DOTALL).group(2)+" "+re.search(r"^(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", line, re.DOTALL).group(3)+":"+re.search(r"^(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", line, re.DOTALL).group(4)+":"+re.search(r"^(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", line, re.DOTALL).group(5)
            #print(time_temp)
            f.write(ip_temp+"@"+time_temp+"\n")
f.close()
print("正在汇总")
result = open("result.txt")
result_txt = result.readlines()
time1 = open("time.txt")
time_txt = time1.readlines()

with open('result.txt', 'w') as f:
    f.write("警告:请勿以记事本打开文本,否则可能出现格式混乱等情况!\n")
    for rline in result_txt:
        rip=find1(r'(?<![\.\d])(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])(?![\.\d])',rline)
        tpan=0
        for tline in time_txt:
            tip=find1(r'(?<![\.\d])(([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])\.){3}([1-9]?\d|1\d\d|2[0-4]\d|25[0-5])(?![\.\d])',tline)
            if(rip==tip):
                time_temp=re.search(r"@(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", tline, re.DOTALL).group(1)+" "+re.search(r"@(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", tline, re.DOTALL).group(2)+" "+re.search(r"@(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", tline, re.DOTALL).group(3)+":"+re.search(r"@(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", tline, re.DOTALL).group(4)+":"+re.search(r"@(\S+)\s(\d+)\s(\d+):(\d+):(\d+)", tline, re.DOTALL).group(5)
                if(has_substring(rline,time_temp)==False):
                    #print(time_temp)
                    if(tpan==0):
                        rline=rline.replace("\n",'')+"*"+time_temp+"\n"
                        tpan=tpan+1
                    else:
                        rline=rline.replace("\n",'')+","+time_temp+"\n"
        f.write(rline)          
f.close()

print("正在生成excel")
wb = xlwt.Workbook(encoding = 'utf-8') #新建一个excel文件
ws1 = wb.add_sheet('first') #添加一个新表,名字为first
result=open("result.txt")
result_txt=result.readlines()
hang=0
for line in result_txt:
    array = line.split('*')
    lie=0
    for i in range(len(array)):
        if(hang==0):
            ws1.write(0,0,"访问IP")
            ws1.write(0,1,"登录次数")
            ws1.write(0,2,"登录用户")
            ws1.write(0,3,"登录时间")
            continue
        ws1.write(hang, lie ,array[i])
        lie=lie+1
    hang=hang+1
#ws1.write(0,0,"访问IP")
#ws1.write(0,1,"登录次数")
#ws1.write(0,2,"登录用户")
#ws1.write(0,3,"登录时间")
wb.save("result.xls") 

try:
    os.remove('time.txt')
    os.remove('result.txt')
    os.remove('user.txt')
    os.remove('ip.txt')
except:
    print("临时文件:ip.txt,user.txt,time.txt或result.txt无法删除,请手动删除")
print("完成!结果见本目录下result.xlsx")
time.sleep(10000)
届ける言葉を今は育ててる
最后更新于 2024-02-07