標籤:
好久沒有更新部落格了,寫了很早的一個指令碼存下檔,一個用於分析使用者登入日誌 /etc/auth.log的指令碼,可以分析
成功、失敗次數,以及來自的IP地址和登入失敗的使用者名稱,可以用於監控是否有暴力密碼破解攻擊,多了就可以用於收集字典,用來避免密碼過於簡單的問題
#/usr/bin/env python3.4#Anyalize the /etc/auth.log files to get# 1) how many failed login trials# 2) how many succeeded login trials# 3) how many IP's where the login trials comes from and what they are# 4) how many invalid usernames are tested and what they are## usage:# anyalyze <filename># note: - for standard input streamimport sysimport re# # of trialsDEBUG_FLAG = 0INFO_FLAG = 0def debug(msg): if DEBUG_FLAG: print("[DEBUG] ", msg)def info(msg): if INFO_FLAG: print("[INFO] ", msg)def openLog( source ): if( source == "-"): return sys.stdin; else: debug("opening file:" + source) f = open(source,'r') return f# failed loginptnFailed = re.compile(r'Failed password for (?P<user>\w+) from (?P<ip>\d+\.\d+\.\d+\.\d+)')# invalid user trailptnInvalid = re.compile(r'Failed password for invalid user (?P<user>\w+) from (?P<ip>\d+\.\d+\.\d+\.\d+)')# login succeededptnSuccess = re.compile(r'Accepted password for (?P<user>\w+) from (?P<ip>\d+\.\d+\.\d+\.\d+)')# sudoptnSudo = re.compile(r'session opened for user (?P<user>\w+) by (?P<ip>\w+)')# >0: valid user & incorreck password# <0: invalid usernFailed = {}nSuccess = {}nSuccess_records = {}ipFailed={}ipSuccess={}if(len(sys.argv) < 2): print("Usage:") print("\t"+sys.argv[0]+" <filename>") print("Note: <filename> can be - for standard input stream") exit(0)log = openLog(sys.argv[1])for line in log: m = ptnFailed.search(line) debug(m) if not m: m = ptnInvalid.search(line) debug(m) if m: user = m.group(ptnInvalid.groupindex['user']) if user not in nFailed: info("[FAILED] Found a new user <" + user + ">"); nFailed[user] = 0 nFailed[user] = nFailed[user]+1 ip = m.group(ptnInvalid.groupindex['ip']) if ip not in ipFailed: ipFailed[ip] = 0 info("[FAILED] Found a new ip <" + ip + ">"); ipFailed[ip] = ipFailed[ip] + 1 else: m = ptnSuccess.search(line) if not m: m = ptnSudo.search(line) debug(m) if m: print(line) user = m.group(ptnSuccess.groupindex['user']) if user not in nSuccess: nSuccess[user] = 0 info("[SUCCESS] Found a new user <" + user + ">"); nSuccess[user] = nSuccess[user]+1 ip = m.group(ptnSuccess.groupindex['ip']) if ip not in ipSuccess: ipSuccess[ip] = 0 info("[SUCCESS] Found a new ip <" + ip + ">"); ipSuccess[ip] = ipSuccess[ip] + 1 else: debug("*** Unknown:" + line)# TODO: close(log) print("nFailed:" )print(nFailed)print("nSuccess:" )print(nSuccess)# a key-value list# it assure that the order is the same to the coming orderclass KeyValue: def __init__(self, key, value): self.key = key self.value = value def __repr__(self): return repr((self.key, self.value))# return a KeyValue list because of the order of the keys in a dictionary# is unexpected, not same to the order as they are put indef sortDict(adict): result=[] keys = sorted(adict.keys(),key=adict.__getitem__, reverse = True) for k in keys: result.append(KeyValue(k,adict[k])) return result# convert a KeyValue list to html table# @return a html stringdef KeyValueList2Html(kvlist, headerMap): html ="<table>\n" hkey = 'Key' hvalue = 'Value' if headerMap: hkey = headerMap['key']; hvalue = headerMap['value']; debug(hkey) debug(hvalue) html+= "<th>"+"<td>"+hkey+'</td>'+'<td>'+hvalue+'</td>'+ '</th>\n' for kv in kvlist: html += "<tr>"+"<td>"+kv.key+'</td>'+'<td>'+str(kv.value)+'</td>'+ '</tr>\n' html += "</table>\n" return htmlprint("------------ Tested user list *Failed* -------------", sortDict(nFailed))print("------------ Source IP *Failed* ------------------",sortDict(ipFailed))print("------------ Login Success -------------", sortDict(nSuccess))print("------------ Source IP *Success* -----------------", sortDict(ipSuccess))# writing result to a HTML reportprint("Wring result to result.html ...")reportFilename = 'auth.log-analysis.html'report = open(reportFilename, 'w')if report: title = 'Auth Log Analysis' report.write('<html>\n') report.write('<head>'+title+'</head>\n') report.write('<style>' + 'table {border:black 1px solid}' +'</style>') report.write("------------ Tested user list *Failed* -------------\n") report.write(KeyValueList2Html(sortDict(nFailed),{'key':'username','value':'# of trial'})) report.write("------------ Source IP *Failed* ------------------") report.write(KeyValueList2Html(sortDict(ipFailed),{'key':'source IP','value':'# of trial'})) report.write("------------ Login Success -------------") report.write(KeyValueList2Html(sortDict(nSuccess),{'key':'username','value':'# of trial'})) report.write("------------ Source IP *Success* -----------------") report.write(KeyValueList2Html(sortDict(ipSuccess),{'key':'source IP','value':'# of login'})) report.write('<body>\n') report.write('</body>\n') report.write('</html>\n')# close(report) print('OK')else: print('Failed to open file:', reportFilename)
SSH登入日誌分析指令碼(Python)