Offene Registrierung gegen Bot-Massenanlage absichern

Auf der Testumgebung liefen seit Juli 2026 taeglich 10-20 automatisierte
Registrierungen, die zufaellige Namen mit fremden echten E-Mail-Adressen
kombinierten - der Server verschickte Vertrags- und Verifikationsmail an
Unbeteiligte. Das IP-Rate-Limit griff nicht, weil jede Anfrage ueber eine
eigene Rechenzentrums-IP kam.

app/spam-guard.php ergaenzt daher Honigtopf, Zeitfalle, eine globale
Notbremse ueber alle IPs hinweg und eine MX/A-Pruefung der Mail-Domain.
Die ersten drei antworten mit derselben generischen Meldung wie das
Rate-Limit, damit die Antwort nicht verraet, welche Huerde angeschlagen
hat; Treffer landen im Error-Log. Bewusst ohne Captcha, um keinen
Drittanbieter in den Registrierungspfad zu holen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 23:09:38 +02:00
co-authored by Claude Opus 5
parent 3346b51b21
commit 86334c2752
4 changed files with 316 additions and 2 deletions
+36
View File
@@ -266,6 +266,42 @@ Stripe-Flow zur Aktualisierung der Zahlungsart. Im Stripe-Dashboard dürfen der
zusätzlich freigeschaltet werden; Bestellungen und Kündigungen sollen nur über
die dokumentierten Abläufe der Kaffeeliste erfolgen.
## Schutz der offenen Registrierung
Ab Juli 2026 liefen auf `testumgebung.kaffeeliste.de` täglich 1020
automatisierte Registrierungen: zufällige Namen kombiniert mit **fremden,
echten** E-Mail-Adressen. Der Server verschickte daraufhin Vertrags- und
Verifikationsmail an Leute, die nie etwas bestellt hatten — Mail-Bombing
über die eigene Domain, auf Kosten der Zustellbarkeit. Das IP-Rate-Limit
griff nicht, weil jede Anfrage über eine eigene Rechenzentrums-IP kam.
`app/spam-guard.php` stellt deshalb vor `register.php`:
- **Honigtopf** — ein für Menschen unsichtbares Feld (`contact_reference`),
das Formular-Bots ausfüllen. Die Positionierung steht bewusst inline und
nicht in `public.css`: lädt das Stylesheet einmal nicht, wäre das Feld
sonst sichtbar und ein echter Nutzer könnte hineinschreiben.
- **Zeitfalle** — mindestens vier Sekunden zwischen Ausliefern und
Absenden des Formulars.
- **Globale Notbremse** — höchstens 20 Registrierungen pro Stunde über
alle IPs hinweg, zusätzlich zum bestehenden Limit von 5 pro IP.
- **Domain-Prüfung** — die Mail-Domain muss einen MX- oder A/AAAA-Record
haben. Fehlt `checkdnsrr()`, wird durchgelassen: eine kaputte
DNS-Auflösung darf keine echten Registrierungen blockieren.
Honigtopf, Zeitfalle und beide Rate-Limits antworten mit **derselben**
generischen Meldung, damit die Antwort nicht verrät, welche Hürde
angeschlagen hat. Treffer stehen im PHP-Error-Log (`Spam-Guard: …`) — dort
lässt sich ablesen, ob die Maßnahmen greifen. Nur die Domain-Prüfung nennt
den Grund, weil das in aller Regel ein Tippfehler eines echten Nutzers ist.
Bewusst **kein** Captcha: Turnstile oder hCaptcha wären wirksam, holen aber
einen Drittanbieter in den Registrierungspfad und damit in die
Datenschutzerklärung. Erst wenn die obigen Hürden nachweislich nicht
reichen, ist das die nächste Stufe.
Abgedeckt von `scripts/check-spam-guard.php` (ohne Datenbank lauffähig).
## Betreiber-Benachrichtigung bei neuer Registrierung
`register.php` schickt nach einer erfolgreichen Selbstregistrierung einen