From b0c8e8efc0cefd805085c227997f739b018080a1 Mon Sep 17 00:00:00 2001 From: UserIsMH Date: Sat, 7 Jun 2025 22:29:33 +0200 Subject: [PATCH] CAPTCHA (Noch kein Key) --- JOURNAL.md | 97 +++++++++++++++++++++++++++++++++- v2/.env | 7 +++ v2_adminpanel/app.py | 59 +++++++++++++++++++-- v2_adminpanel/requirements.txt | 1 + 4 files changed, 160 insertions(+), 4 deletions(-) diff --git a/JOURNAL.md b/JOURNAL.md index 795b1ef..8ec6e78 100644 --- a/JOURNAL.md +++ b/JOURNAL.md @@ -801,4 +801,99 @@ Die Session-Daten werden erst gefüllt, wenn der License Server API implementier **Status:** - ✅ Session-Timeout-Mechanismus vollständig implementiert - ✅ Debug-Logging für Session-Überwachung aktiv -- ✅ Cookie-Sicherheitseinstellungen optimiert \ No newline at end of file +- ✅ Cookie-Sicherheitseinstellungen optimiert + +### 2025-06-07 - CAPTCHA Backend-Validierung implementiert +- Google reCAPTCHA v2 Backend-Verifizierung hinzugefügt + +**Implementierte Features:** +1. **verify_recaptcha() Funktion (app.py):** + - Validiert CAPTCHA-Response mit Google API + - Fallback: Wenn RECAPTCHA_SECRET_KEY nicht konfiguriert, wird CAPTCHA übersprungen (für PoC) + - Timeout von 5 Sekunden für API-Request + - Error-Handling für Netzwerkfehler + - Logging für Debugging und Fehleranalyse + +2. **Login-Route Erweiterungen:** + - CAPTCHA wird nach 2 Fehlversuchen angezeigt + - Prüfung ob CAPTCHA-Response vorhanden + - Validierung der CAPTCHA-Response gegen Google API + - Unterschiedliche Fehlermeldungen für fehlende/ungültige CAPTCHA + - Site Key wird aus Environment-Variable an Template übergeben + +3. **Environment-Konfiguration (.env):** + - RECAPTCHA_SITE_KEY (für Frontend) + - RECAPTCHA_SECRET_KEY (für Backend-Validierung) + - Beide auskommentiert für PoC-Phase + +4. **Dependencies:** + - requests Library zu requirements.txt hinzugefügt + +**Sicherheitsaspekte:** +- CAPTCHA verhindert automatisierte Brute-Force-Angriffe +- Timing-Attack-Schutz bleibt auch bei CAPTCHA-Prüfung aktiv +- Bei Netzwerkfehlern wird CAPTCHA als bestanden gewertet (Verfügbarkeit vor Sicherheit) +- Secret Key wird niemals im Frontend exponiert + +**Verwendung:** +1. Google reCAPTCHA v2 Keys erstellen: https://www.google.com/recaptcha/admin +2. Keys in .env eintragen: + ``` + RECAPTCHA_SITE_KEY=your-site-key + RECAPTCHA_SECRET_KEY=your-secret-key + ``` +3. Container neu starten + +**Status:** +- ✅ CAPTCHA-Frontend bereits vorhanden (login.html) +- ✅ Backend-Validierung vollständig implementiert +- ✅ Fallback für PoC-Betrieb ohne Google-Keys +- ✅ Integration in Rate-Limiting-System +- ⚠️ CAPTCHA-Keys noch nicht konfiguriert (für PoC deaktiviert) + +**Anleitung für Google reCAPTCHA Keys:** + +1. **Registrierung bei Google reCAPTCHA:** + - Gehe zu: https://www.google.com/recaptcha/admin/create + - Melde dich mit Google-Konto an + - Label eingeben: "v2-Docker Admin Panel" + - Typ wählen: "reCAPTCHA v2" → "Ich bin kein Roboter"-Kästchen + - Domains hinzufügen: + ``` + admin-panel-undso.z5m7q9dk3ah2v1plx6ju.com + localhost + ``` + - Nutzungsbedingungen akzeptieren + - Senden klicken + +2. **Keys erhalten:** + - Site Key (öffentlich für Frontend) + - Secret Key (geheim für Backend-Validierung) + +3. **Keys in .env eintragen:** + ```bash + RECAPTCHA_SITE_KEY=6Ld... + RECAPTCHA_SECRET_KEY=6Ld... + ``` + +4. **Container neu starten:** + ```bash + docker-compose down + docker-compose up -d + ``` + +**Kosten:** +- Kostenlos bis 1 Million Anfragen pro Monat +- Danach: $1.00 pro 1000 zusätzliche Anfragen +- Für dieses Projekt reicht die kostenlose Version vollkommen aus + +**Test-Keys für Entwicklung:** +- Site Key: `6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI` +- Secret Key: `6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe` +- ⚠️ Diese Keys nur für lokale Tests verwenden, niemals produktiv! + +**Aktueller Status:** +- Code ist vollständig implementiert und getestet +- CAPTCHA wird nach 2 Fehlversuchen angezeigt +- Ohne konfigurierte Keys wird CAPTCHA-Prüfung übersprungen +- Für Produktion müssen nur die Keys in .env eingetragen werden \ No newline at end of file diff --git a/v2/.env b/v2/.env index ff5f0e8..3a27e3f 100644 --- a/v2/.env +++ b/v2/.env @@ -47,3 +47,10 @@ EMAIL_ENABLED=false # Backup-Verschlüsselung (optional, wird automatisch generiert wenn leer) # BACKUP_ENCRYPTION_KEY= + +# ===================== CAPTCHA KONFIGURATION ===================== + +# Google reCAPTCHA v2 Keys (https://www.google.com/recaptcha/admin) +# Für PoC-Phase auskommentiert - CAPTCHA wird übersprungen wenn Keys fehlen +# RECAPTCHA_SITE_KEY=your-site-key-here +# RECAPTCHA_SECRET_KEY=your-secret-key-here diff --git a/v2_adminpanel/app.py b/v2_adminpanel/app.py index 1f13359..a1d356b 100644 --- a/v2_adminpanel/app.py +++ b/v2_adminpanel/app.py @@ -17,6 +17,7 @@ from apscheduler.schedulers.background import BackgroundScheduler import logging import random import hashlib +import requests load_dotenv() @@ -512,6 +513,41 @@ def send_security_alert_email(ip_address, username, attempt_count): logging.warning(f"Sicherheitswarnung: {attempt_count} fehlgeschlagene Versuche von IP {ip_address}") print(f"E-Mail würde gesendet: {subject}") +def verify_recaptcha(response): + """Verifiziert die reCAPTCHA v2 Response mit Google""" + secret_key = os.getenv('RECAPTCHA_SECRET_KEY') + + # Wenn kein Secret Key konfiguriert ist, CAPTCHA als bestanden werten (für PoC) + if not secret_key: + logging.warning("RECAPTCHA_SECRET_KEY nicht konfiguriert - CAPTCHA wird übersprungen") + return True + + # Verifizierung bei Google + try: + verify_url = 'https://www.google.com/recaptcha/api/siteverify' + data = { + 'secret': secret_key, + 'response': response + } + + # Timeout für Request setzen + r = requests.post(verify_url, data=data, timeout=5) + result = r.json() + + # Log für Debugging + if not result.get('success'): + logging.warning(f"reCAPTCHA Validierung fehlgeschlagen: {result.get('error-codes', [])}") + + return result.get('success', False) + + except requests.exceptions.RequestException as e: + logging.error(f"reCAPTCHA Verifizierung fehlgeschlagen: {str(e)}") + # Bei Netzwerkfehlern CAPTCHA als bestanden werten + return True + except Exception as e: + logging.error(f"Unerwarteter Fehler bei reCAPTCHA: {str(e)}") + return False + @app.route("/login", methods=["GET", "POST"]) def login(): # Timing-Attack Schutz - Start Zeit merken @@ -545,7 +581,22 @@ def login(): return render_template("login.html", error="CAPTCHA ERFORDERLICH!", show_captcha=True, - error_type="captcha") + error_type="captcha", + attempts_left=max(0, MAX_LOGIN_ATTEMPTS - attempt_count), + recaptcha_site_key=os.getenv('RECAPTCHA_SITE_KEY')) + + # CAPTCHA validieren + if not verify_recaptcha(captcha_response): + # Timing-Attack Schutz + elapsed = time.time() - start_time + if elapsed < 1.0: + time.sleep(1.0 - elapsed) + return render_template("login.html", + error="CAPTCHA UNGÜLTIG! Bitte erneut versuchen.", + show_captcha=True, + error_type="captcha", + attempts_left=max(0, MAX_LOGIN_ATTEMPTS - attempt_count), + recaptcha_site_key=os.getenv('RECAPTCHA_SITE_KEY')) # Check gegen beide Admin-Accounts aus .env admin1_user = os.getenv("ADMIN1_USERNAME") @@ -589,12 +640,14 @@ def login(): error=error_message, show_captcha=(new_attempt_count >= CAPTCHA_AFTER_ATTEMPTS), error_type="failed", - attempts_left=max(0, MAX_LOGIN_ATTEMPTS - new_attempt_count)) + attempts_left=max(0, MAX_LOGIN_ATTEMPTS - new_attempt_count), + recaptcha_site_key=os.getenv('RECAPTCHA_SITE_KEY')) # GET Request return render_template("login.html", show_captcha=(attempt_count >= CAPTCHA_AFTER_ATTEMPTS), - attempts_left=max(0, MAX_LOGIN_ATTEMPTS - attempt_count)) + attempts_left=max(0, MAX_LOGIN_ATTEMPTS - attempt_count), + recaptcha_site_key=os.getenv('RECAPTCHA_SITE_KEY')) @app.route("/logout") def logout(): diff --git a/v2_adminpanel/requirements.txt b/v2_adminpanel/requirements.txt index 6c72e49..342f0e3 100644 --- a/v2_adminpanel/requirements.txt +++ b/v2_adminpanel/requirements.txt @@ -7,3 +7,4 @@ pandas openpyxl cryptography apscheduler +requests