ub ln

 avatar
Lattuse
python
9 months ago
3.3 kB
12
Indexable
#!/usr/bin/env python3
"""
security_log_analyzer.py
Usage:
  sudo python3 security_log_analyzer.py
  sudo python3 security_log_analyzer.py --log /path/to/auth.log
"""

import re
import os
import sys
from collections import Counter
import argparse

parser = argparse.ArgumentParser(description='Security Log Analyzer')
parser.add_argument('--log', default='/var/log/auth.log',
                    help='Path to auth log (default: /var/log/auth.log)')
args = parser.parse_args()

log_path = args.log
if not os.path.exists(log_path):
    if os.path.exists('sample_log.txt'):
        print(f"{log_path} not found — will use sample_log.txt")
        log_path = 'sample_log.txt'
    else:
        print(f"No log file found at {args.log} and no sample_log.txt present.")
        sys.exit(1)

ip_re = re.compile(r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b')
# username patterns: "for invalid user <user>" or "for <user>" or "user=<user>"
u1 = re.compile(r'for (?:invalid user )?([^\s:]+)')
u2 = re.compile(r'user=([^\s,;]+)')

ip_counts = Counter()
user_counts = Counter()

with open(log_path, 'r', errors='ignore') as fh:
    for line in fh:
        if re.search(r'(?i)failed|failure|invalid user|authentication failure|Failed password', line):
            ips = ip_re.findall(line)
            for ip in ips:
                ip_counts[ip] += 1
            m = u1.search(line)
            if not m:
                m = u2.search(line)
            if m:
                user = m.group(1)
                user_counts[user] += 1

# Write suspicious_activity.txt: CSV-like (IP, attempts)
with open('suspicious_activity.txt', 'w') as out:
    out.write('IP,attempts\n')
    for ip, cnt in ip_counts.most_common():
        out.write(f'{ip},{cnt}\n')

print(f"Wrote suspicious_activity.txt ({len(ip_counts)} unique IPs)")

# Check /etc/passwd -> home directories with insecure permissions
insecure = []
if os.path.exists('/etc/passwd'):
    with open('/etc/passwd') as pf:
        for line in pf:
            parts = line.strip().split(':')
            if len(parts) < 6:
                continue
            username, home = parts[0], parts[5]
            if not home or not os.path.isdir(home):
                continue
            try:
                mode = os.stat(home).st_mode & 0o777
                # считаем небезопасным, если точно 0o777 или есть запись для group/other
                if mode == 0o777 or (mode & 0o077) == 0o077:
                    insecure.append((username, home, oct(mode)))
            except Exception:
                continue

with open('insecure_homes.txt', 'w') as out:
    if insecure:
        out.write('username:home:mode\n')
        for u, h, m in insecure:
            out.write(f'{u}:{h}:{m}\n')
        print(f"Wrote insecure_homes.txt ({len(insecure)} insecure dirs found)")
    else:
        out.write('No insecure home directories found\n')
        print("No insecure home directories found")

# Optionally print top usernames
if user_counts:
    print("Top usernames found in failed attempts (sample):")
    for user, cnt in user_counts.most_common(10):
        print(f"  {user}: {cnt}")
Editor is loading...
Leave a Comment