Update q4-siem/siem_analyzer.py

هذا الالتزام موجود في:
2026-07-27 12:01:02 +00:00
الأصل 45852d276b
التزام f7df451f8f

عرض الملف

@@ -1,24 +1,122 @@
#!/usr/bin/env python3
"""
Ghaymah Lightweight SIEM Engine
Author: AbdulRhman Ewais
Description: Consolidated Log Analyzer for Auth, Nginx, and API services.
"""
import os
import re
import json
from collections import defaultdict
LOG_FILE = "ghaymah_access.log"
FAILED_THRESHOLD = 5
# مسارات السجلات الافتراضية المربوطة بالـ Volume
LOG_SOURCES = {
"auth": "/var/log/siem_logs/auth.log",
"web": "/var/log/siem_logs/nginx_access.log",
"api": "/var/log/siem_logs/ghaymah_api.log"
}
ip_failures = defaultdict(int)
# أنماط الكشف (Detection Signatures)
BRUTE_FORCE_THRESHOLD = 5
XSS_PATTERN = re.compile(r'(<script>|javascript:|onerror=|onload=)', re.IGNORECASE)
SQLI_PATTERN = re.compile(r'(UNION\s+SELECT|SELECT\s+.*\s+FROM|OR\s+1\s*=\s*1|--|/\*|\*/)', re.IGNORECASE)
log_pattern = re.compile(r'(?P<ip>\d+\.\d+\.\d+\.\d+) - - \[.*?\] "(?P<method>\w+) (?P<path>\S+) HTTP/.*?" (?P<status>\d{3})')
def parse_auth_logs(filepath):
"""تحليل سجلات المصادقة لكشف هجمات الـ SSH Brute Force"""
alerts = []
failed_attempts = defaultdict(int)
if not os.path.exists(filepath):
return alerts
try:
with open(LOG_FILE, 'r') as f:
# النمط: Failed password for invalid user admin from 192.168.1.50 port 54322 ssh2
pattern = re.compile(r'Failed password for .* from (?P<ip>\d+\.\d+\.\d+\.\d+)')
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
match = log_pattern.search(line)
match = pattern.search(line)
if match:
ip = match.group('ip')
failed_attempts[ip] += 1
if failed_attempts[ip] == BRUTE_FORCE_THRESHOLD:
alerts.append({
"source": "Auth Logs (SSH)",
"ip": ip,
"type": "SSH Brute Force Attempt",
"severity": "High",
"details": f"Detected {failed_attempts[ip]} failed SSH logins."
})
return alerts
def parse_web_logs(filepath):
"""تحليل سجلات Nginx لكشف محاولات الاختراق (SQLi / XSS)"""
alerts = []
if not os.path.exists(filepath):
return alerts
# النمط القياسي لـ Nginx Log
pattern = re.compile(r'(?P<ip>\d+\.\d+\.\d+\.\d+) - - \[.*\] "(?P<method>\w+) (?P<path>\S+) HTTP/.*" (?P<status>\d{3})')
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
match = pattern.search(line)
if match:
data = match.groupdict()
if data['status'] == '401' and '/login' in data['path']:
ip_failures[data['ip']] += 1
if ip_failures[data['ip']] >= FAILED_THRESHOLD:
print(f"[ALERT] High Brute Force Risk: {data['ip']} ({ip_failures[data['ip']]} failed attempts)")
if "select" in data['path'].lower() or "union" in data['path'].lower():
print(f"[CRITICAL] Potential SQL Injection from {data['ip']}: {data['path']}")
except FileNotFoundError:
print(f"Log file {LOG_FILE} not found. Ready for deployment.")
path_decoded = data['path']
if SQLI_PATTERN.search(path_decoded):
alerts.append({
"source": "Web Logs (Nginx)",
"ip": data['ip'],
"type": "SQL Injection Attempt",
"severity": "Critical",
"details": f"Suspicious pattern in URL: {path_decoded}"
})
elif XSS_PATTERN.search(path_decoded):
alerts.append({
"source": "Web Logs (Nginx)",
"ip": data['ip'],
"type": "Cross-Site Scripting (XSS)",
"severity": "High",
"details": f"Payload detected in path: {path_decoded}"
})
return alerts
def parse_api_logs(filepath):
"""تحليل سجلات تطبيق غيمة لكشف إساءة استخدام الـ Token أو الـ Rate Limit"""
alerts = []
if not os.path.exists(filepath):
return alerts
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
try:
log_data = json.loads(line)
if log_data.get("status") == 429: # Too Many Requests
alerts.append({
"source": "Ghaymah API",
"ip": log_data.get("client_ip", "Unknown"),
"type": "API Rate Limit Exceeded",
"severity": "Medium",
"details": f"Client hammered Endpoint: {log_data.get('endpoint')}"
})
except json.JSONDecodeError:
continue
return alerts
def main():
all_alerts = []
all_alerts.extend(parse_auth_logs(LOG_SOURCES["auth"]))
all_alerts.extend(parse_web_logs(LOG_SOURCES["web"]))
all_alerts.extend(parse_api_logs(LOG_SOURCES["api"]))
# تصدير النتائج لملف JSON لتقرأه الـ Dashboard
output_path = "/var/log/siem_logs/siem_alerts.json"
with open(output_path, 'w', encoding='utf-8') as out_f:
json.dump(all_alerts, out_f, indent=4)
print(f"[+] SIEM Analysis complete. {len(all_alerts)} alerts written to {output_path}")
if __name__ == "__main__":
main()