From 03f8754c1db64fa5b34c11e3c62b4f62afc4ad56 Mon Sep 17 00:00:00 2001
From: "Popal, Massi" <massi.popal@studium.uni-hamburg.de>
Date: Sun, 23 Mar 2025 21:01:10 +0000
Subject: [PATCH] Upload New File

---
 gbac_server.py | 156 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 156 insertions(+)
 create mode 100644 gbac_server.py

diff --git a/gbac_server.py b/gbac_server.py
new file mode 100644
index 0000000..b574811
--- /dev/null
+++ b/gbac_server.py
@@ -0,0 +1,156 @@
+#!/usr/bin/python3
+
+from flask import Flask, request, jsonify
+import ssl
+import sqlite3
+from typing import List, Dict
+import logging
+import requests
+import json
+import networkx as nx
+import os
+
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+
+app = Flask(__name__)
+
+conn = sqlite3.connect("iocs.db", check_same_thread=False)
+conn.execute("CREATE TABLE IF NOT EXISTS iocs (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT)")
+
+def gac_connect(time_window: float = 300.0) -> List[Dict]:
+    """Identify multi-step attacks by constructing a directed graph of IoCs based on time and entity overlap."""
+    cursor = conn.execute("SELECT data FROM iocs")
+    iocs = [json.loads(row[0]) for row in cursor.fetchall()]
+    if not iocs:
+        return []
+
+    G = nx.DiGraph()
+    for ioc in iocs:
+        G.add_node(ioc["timestamp"], data=ioc)
+    
+    for i, ioc1 in enumerate(iocs):
+        for ioc2 in iocs[i+1:]:
+            time_diff = float(ioc2["timestamp"]) - float(ioc1["timestamp"])
+            if time_diff <= time_window and (set(ioc1["attackers"]) & set(ioc2["attackers"]) or set(ioc1["victims"]) & set(ioc2["victims"])):
+                G.add_edge(ioc1["timestamp"], ioc2["timestamp"])
+    
+    multi_step_attacks = []
+    for component in nx.weakly_connected_components(G):
+        nodes = sorted([G.nodes[n]["data"] for n in component], key=lambda x: float(x["timestamp"]))
+        if len(nodes) <= 1:
+            continue
+        attackers, victims, details = set(), set(), []
+        attack_type = nodes[0]["pattern"]
+        for i, node in enumerate(nodes):
+            attackers.update(node["attackers"])
+            victims.update(node["victims"])
+            details.append(node)
+            if i > 0:
+                prev_type, curr_type = nodes[i-1]["pattern"], node["pattern"]
+                if "Portscan" in prev_type and "Exploitation" in curr_type:
+                    attack_type = "Portscan followed by Exploitation"
+                elif "Exploitation" in prev_type and "DDoS" in curr_type:
+                    attack_type = "Exploitation followed by DDoS"
+                elif "Portscan" in prev_type and "DDoS" in curr_type:
+                    attack_type = "Portscan followed by DDoS"
+                elif "Exploitation" in prev_type and "Worm Propagation" in curr_type:
+                    attack_type = "Exploitation followed by Worm Propagation"
+                else:
+                    attack_type = f"{attack_type} and {curr_type}"
+        multi_step_attacks.append({
+            "type": attack_type,
+            "attackers": list(attackers),
+            "victims": list(victims),
+            "details": details,
+            "network_id": nodes[0]["network_id"]
+        })
+    
+    for attack in multi_step_attacks:
+        logging.info(f"Multi-Step Attack in {attack['network_id']} detected: {attack['type']}")
+    return multi_step_attacks
+
+@app.route('/submit_ioc', methods=['POST'])
+def submit_ioc():
+    """Process incoming IoCs, store them, and trigger alert generation."""
+    ioc_data = request.json
+    for ioc in ioc_data:
+        conn.execute("INSERT INTO iocs (data) VALUES (?)", (json.dumps(ioc),))
+    conn.commit()
+    logging.info(f"Received IoCs: {len(ioc_data)} from Network {ioc_data[0]['network_id']}")
+    
+    network_ids = set(ioc["network_id"] for ioc in ioc_data)
+    multi_step_attacks = gac_connect()
+    messages = []
+    
+    if multi_step_attacks:
+        messages = send_alerts(multi_step_attacks, multi_step=True, network_ids=network_ids)
+    else:
+        cursor = conn.execute("SELECT data FROM iocs")
+        iocs = [json.loads(row[0]) for row in cursor.fetchall()]
+        if iocs:
+            messages = send_alerts(iocs, multi_step=False, network_ids=network_ids)
+    
+    # Print messages at the end
+    if messages:
+        print("\n=== Nachrichten an Netzwerke ===")
+        for msg in messages:
+            print(msg)
+        print("====================\n")
+    
+    return jsonify({"status": "success"}), 200
+
+def send_alerts(attacks_or_iocs, multi_step: bool, network_ids: set) -> List[str]:
+    """Transmit alerts to client networks via HTTPS and return tailored messages."""
+    messages = []
+    for item in attacks_or_iocs:
+        source_network = item["network_id"]
+        alert_type = item["type"] if multi_step else item["pattern"]
+        attackers, victims = item["attackers"], item["victims"]
+        
+        if "Portscan" in alert_type:
+            recommendation = "Blockiere die Quell-IPs und überprüfe die Zielsysteme auf Scan-Aktivitäten."
+        elif "Exploitation" in alert_type:
+            recommendation = "Isoliere die betroffenen Systeme und überprüfe sie auf Kompromittierung."
+        elif "DDoS" in alert_type:
+            recommendation = "Erhöhe die Netzwerksicherheit und blockiere die Angreifer-IPs."
+        elif "Worm Propagation" in alert_type:
+            recommendation = "Quarantäne infizierte Systeme und führe eine Netzwerkbereinigung durch."
+        else:
+            recommendation = "Blockiere Angreifer-IPs und überprüfe Zielsysteme auf Kompromittierung."
+
+        for network_id in network_ids:
+            if network_id == source_network:
+                message = f"In deinem Netzwerk wurde ein {alert_type} erkannt."
+            else:
+                message = f"Im angebundenen Netzwerk {source_network} wurde ein {alert_type} erkannt."
+            
+            alert_plus = {
+                "type": alert_type,
+                "attackers": attackers,
+                "victims": victims,
+                "source_network": source_network,
+                "current_network": network_id,
+                "recommendation": recommendation,
+                "message": message  # Include the tailored message in the alert
+            }
+            network_url = f"https://{network_id.lower()}.local:8080/alert"
+            try:
+                response = requests.post(network_url, json=alert_plus, verify=False)
+                if response.status_code == 200:
+                    logging.info(f"Alert Plus sent to {network_id}: {message}")
+                    messages.append(f"An {network_id}: {message} Empfehlung: {recommendation}")
+                else:
+                    logging.error(f"Error sending to {network_id}: {response.status_code}")
+            except Exception as e:
+                logging.error(f"Connection error sending to {network_id}: {e}")
+    
+    return messages
+
+if __name__ == "__main__":
+    context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
+    cert_path = "cert.pem"
+    key_path = "key.pem"
+    if not (os.path.exists(cert_path) and os.path.exists(key_path)):
+        raise FileNotFoundError("SSL certificates (cert.pem, key.pem) not found. Generate them with OpenSSL.")
+    context.load_cert_chain(cert_path, key_path)
+    app.run(host='0.0.0.0', port=443, ssl_context=context, threaded=False)
\ No newline at end of file
-- 
GitLab