import requests import time import json from datetime import datetime import statistics def test_admin_login_timing(): """Detaillierte Timing-Analyse für Admin Login""" base_url = "http://localhost:3000/api/v1/public/login" # Erweiterte Liste von Admin-Usernamen admin_usernames = [ "admin", "administrator", "root", "user", "test", "demo", "admin1", "admin2", "superuser", "manager", "operator", "ninja", "parkour", "system", "api", "service", "backup", "support", "helpdesk", "it", "tech" ] print("🔍 DETAILLIERTE ADMIN LOGIN TIMING-ANALYSE") print("=" * 70) print(f"Zeit: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"Target: {base_url}") print("=" * 70) results = [] # Teste jeden Username mehrfach für bessere Statistik for username in admin_usernames: times = [] print(f"\n👤 Testing: {username}") print("-" * 50) for attempt in range(5): # 5 Versuche pro Username try: start_time = time.time() response = requests.post( base_url, json={"username": username, "password": "wrongpassword123"}, timeout=10 ) end_time = time.time() response_time = (end_time - start_time) * 1000 # in ms times.append(response_time) print(f" Attempt {attempt+1}: {response_time:6.1f}ms | Status: {response.status_code}") # Kleine Pause zwischen Requests time.sleep(0.1) except Exception as e: print(f" Attempt {attempt+1}: ERROR - {e}") continue if times: avg_time = statistics.mean(times) std_dev = statistics.stdev(times) if len(times) > 1 else 0 min_time = min(times) max_time = max(times) results.append({ 'username': username, 'avg_time': avg_time, 'std_dev': std_dev, 'min_time': min_time, 'max_time': max_time, 'times': times, 'suspicious': avg_time > 50 # Verdächtig wenn > 50ms }) print(f" 📊 Stats: Avg={avg_time:.1f}ms, Std={std_dev:.1f}ms, Range={min_time:.1f}-{max_time:.1f}ms") if avg_time > 50: print(f" ⚠️ SUSPEKT: Deutlich längere Response-Zeit!") # Sortiere nach durchschnittlicher Response-Zeit results.sort(key=lambda x: x['avg_time'], reverse=True) print("\n" + "=" * 70) print("📈 TIMING-ANALYSE ERGEBNISSE") print("=" * 70) print(f"{'Username':<15} {'Avg(ms)':<8} {'Std(ms)':<8} {'Min(ms)':<8} {'Max(ms)':<8} {'Status'}") print("-" * 70) for result in results: status = "⚠️ SUSPEKT" if result['suspicious'] else "✅ Normal" print(f"{result['username']:<15} {result['avg_time']:<8.1f} {result['std_dev']:<8.1f} " f"{result['min_time']:<8.1f} {result['max_time']:<8.1f} {status}") # Speichere detaillierte Ergebnisse timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"timing_analysis_{timestamp}.json" with open(filename, 'w', encoding='utf-8') as f: json.dump(results, f, indent=2, ensure_ascii=False) print(f"\n💾 Detaillierte Ergebnisse gespeichert in: {filename}") return results def test_rfid_creation_enumeration(): """Teste RFID Enumeration über Spieler-Erstellung""" base_url = "http://localhost:3000/api/v1/public/players/create-with-rfid" print("\n🔍 RFID ENUMERATION ÜBER SPIELER-ERSTELLUNG") print("=" * 70) print(f"Zeit: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"Target: {base_url}") print("=" * 70) found_rfids = [] # Teste verschiedene RFID-Patterns test_patterns = [ "AA:BB:CC:DD", "AA:BB:CC:DE", "AA:BB:CC:DF", "11:22:33:44", "11:22:33:45", "11:22:33:46", "FF:FF:FF:FF", "00:00:00:00", "12:34:56:78", "AB:CD:EF:12", "DE:AD:BE:EF", "CA:FE:BA:BE" ] for i, rfid in enumerate(test_patterns, 1): try: payload = { "rfiduid": rfid, "firstname": "Test", "lastname": "User", "birthdate": "1990-01-01" } response = requests.post(base_url, json=payload, timeout=5) print(f"[{i:2d}] RFID: {rfid:<12} | Status: {response.status_code:3d}", end="") if response.status_code == 400: try: data = response.json() if "existiert bereits" in data.get("message", ""): print(" | ✅ EXISTIERT!") if "existingPlayer" in data.get("details", {}): existing = data["details"]["existingPlayer"] found_rfids.append({ "rfid": rfid, "existing_player": existing }) print(f" → Name: {existing.get('firstname')} {existing.get('lastname')}") else: print(" | ❌ Anderer Fehler") except: print(" | ❌ JSON Parse Error") else: print(" | ⚠️ Unexpected Status") except Exception as e: print(f"[{i:2d}] RFID: {rfid:<12} | ERROR: {e}") print(f"\n📊 RFID Enumeration abgeschlossen: {len(found_rfids)} gefunden") return found_rfids def test_leaderboard_data_leak(): """Teste Leaderboard auf sensible Daten""" base_url = "http://localhost:3000/api/v1/public/times-with-details" print("\n🔍 LEADERBOARD DATENLEAK-TEST") print("=" * 70) print(f"Zeit: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print(f"Target: {base_url}") print("=" * 70) try: response = requests.get(base_url, timeout=10) print(f"Status: {response.status_code}") if response.status_code == 200: data = response.json() if isinstance(data, list) and len(data) > 0: print(f"✅ Leaderboard-Daten gefunden: {len(data)} Einträge") # Analysiere erste paar Einträge for i, entry in enumerate(data[:3]): print(f"\n📋 Eintrag {i+1}:") if 'player' in entry: player = entry['player'] print(f" Name: {player.get('firstname')} {player.get('lastname')}") print(f" RFID: {player.get('rfiduid')}") print(f" ID: {player.get('id')}") if 'location' in entry: location = entry['location'] print(f" Location: {location.get('name')}") print(f" Koordinaten: {location.get('latitude')}, {location.get('longitude')}") if 'recorded_time_seconds' in entry: print(f" Zeit: {entry['recorded_time_seconds']} Sekunden") # Speichere alle Daten timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") filename = f"leaderboard_data_{timestamp}.json" with open(filename, 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, ensure_ascii=False) print(f"\n💾 Leaderboard-Daten gespeichert in: {filename}") return data else: print("❌ Keine Leaderboard-Daten gefunden") else: print(f"❌ Fehler: HTTP {response.status_code}") except Exception as e: print(f"🔥 Fehler beim Abrufen der Leaderboard-Daten: {e}") return None def test_error_message_analysis(): """Analysiere Error Messages auf Information Leakage""" base_url = "http://localhost:3000/api/v1/public/user-player" print("\n🔍 ERROR MESSAGE ANALYSE") print("=" * 70) test_uuids = [ "00000000-0000-0000-0000-000000000000", # Null UUID "invalid-uuid-format", # Ungültiges Format "12345678-1234-1234-1234-123456789012", # Gültiges Format, aber wahrscheinlich nicht existent "../../../etc/passwd", # Path Traversal "", # XSS Test "'; DROP TABLE players; --" # SQL Injection Test ] error_responses = {} for i, test_input in enumerate(test_uuids, 1): try: response = requests.get(f"{base_url}/{test_input}", timeout=5) status_code = response.status_code print(f"[{i}] Input: {test_input:<30} | Status: {status_code}") if status_code not in error_responses: error_responses[status_code] = [] try: json_data = response.json() error_responses[status_code].append({ 'input': test_input, 'response': json_data }) except: error_responses[status_code].append({ 'input': test_input, 'response': response.text[:200] # Erste 200 Zeichen }) except Exception as e: print(f"[{i}] Input: {test_input:<30} | ERROR: {e}") # Analysiere verschiedene Error-Messages print(f"\n📊 Error-Message Analyse:") print("-" * 50) for status_code, responses in error_responses.items(): print(f"Status {status_code}: {len(responses)} Responses") # Prüfe auf unterschiedliche Error-Messages unique_messages = set() for resp in responses: if isinstance(resp['response'], dict): message = resp['response'].get('message', 'No message') else: message = str(resp['response'])[:100] unique_messages.add(message) print(f" Unique messages: {len(unique_messages)}") for msg in list(unique_messages)[:3]: # Zeige erste 3 print(f" - {msg}") return error_responses if __name__ == "__main__": print("🚨 NINJA SERVER - REALISTISCHE SICHERHEITSTESTS") print("⚠️ WARNUNG: Nur für autorisierte Sicherheitstests!") print() # 1. Admin Login Timing Analysis timing_results = test_admin_login_timing() # 2. RFID Enumeration über Spieler-Erstellung rfid_results = test_rfid_creation_enumeration() # 3. Leaderboard Datenleak-Test leaderboard_data = test_leaderboard_data_leak() # 4. Error Message Analysis error_analysis = test_error_message_analysis() print("\n" + "=" * 70) print("🏁 REALISTISCHE SICHERHEITSTESTS ABGESCHLOSSEN") print("=" * 70) # Zusammenfassung suspicious_users = [r for r in timing_results if r['suspicious']] print(f"🔍 Timing-Suspicious Users: {len(suspicious_users)}") print(f"🔍 Gefundene RFIDs: {len(rfid_results)}") print(f"🔍 Leaderboard-Einträge: {len(leaderboard_data) if leaderboard_data else 0}") if suspicious_users: print(f"\n⚠️ SUSPEKTE USERNAMES (Timing):") for user in suspicious_users: print(f" - {user['username']}: {user['avg_time']:.1f}ms") print(f"\n⏰ Abgeschlossen um: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")