<?php /** * blitzbestaetigung_process.php * Erkennt Bots, die einen Bestaetigungslink ungewoehnlich schnell nach der * Anmeldung anklicken (z. B. automatisiertes Adress-Scanning bei fremden * Organisationen). Kriterium: kurze Zeitspanne UND abweichende IP zwischen * Anmeldung und Bestaetigung (siehe Wiki-Kapitel 7.2 fuer die Begruendung, * warum reine Zeitspanne allein NICHT ausreicht). * * Verhalten bei Treffer: * - Abonnent wird auf "unbestaetigt" zurueckgesetzt * - IP wird zur Sperrliste vorgemerkt (Attribut "IP sperren") * - NUR die IP wird an Stop Forum Spam gemeldet, NICHT die E-Mail-Adresse * (koennte einem unbeteiligten Dritten gehoeren, siehe Wiki-Kapitel 7.4) * * Voraussetzungen: * - phpList-Attribut "IP sperren" (Checkbox, siehe blocklist_update.php) * - phpList-Attribut "Blitzbestaetigung - eher Bots" (Checkbox, Duplikatschutz) * * WICHTIG: Vor produktivem Einsatz zunaechst nur mit SELECT testen * (siehe Wiki-Kapitel 7.5)! * * Aufruf: per Cron, z. B. stuendlich */ $dbHost = '127.0.0.1'; $dbName = 'DEINE_DB'; $dbUser = 'DEIN_DB_USER'; $dbPass = 'DEIN_DB_PASSWORT'; $sfsApiKey = 'DEIN_STOPFORUMSPAM_API_KEY'; $pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass); $attrIpBlockId = X; // ID des "IP sperren"-Attributs $attrBlitzId = Y; // ID des "Blitzbestaetigung"-Attributs $thresholdSeconds = 120; // < 2 Minuten zwischen Anmeldung und Bestaetigung = verdaechtig $sql = "SELECT u.id, u.email, sub.ip AS sub_ip, conf.ip AS conf_ip, TIMESTAMPDIFF(SECOND, sub.date, conf.date) AS diff_seconds FROM phplist_user_user u JOIN phplist_user_user_history sub ON sub.userid = u.id AND sub.summary IN ('Subscription','Re-Subscription') JOIN phplist_user_user_history conf ON conf.userid = u.id AND conf.summary = 'Confirmation' LEFT JOIN phplist_user_user_attribute uab ON uab.userid = u.id AND uab.attributeid = :blitzId WHERE u.confirmed = 1 AND TIMESTAMPDIFF(SECOND, sub.date, conf.date) BETWEEN 0 AND :threshold AND sub.ip != conf.ip AND (uab.value IS NULL OR uab.value = '') GROUP BY u.id"; $stmt = $pdo->prepare($sql); $stmt->execute(['blitzId' => $attrBlitzId, 'threshold' => $thresholdSeconds]); $candidates = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($candidates as $c) { // 1. Abonnent auf "unbestaetigt" zuruecksetzen $reset = $pdo->prepare("UPDATE phplist_user_user SET confirmed = 0 WHERE id = :uid"); $reset->execute(['uid' => $c['id']]); // 2. IP zur Sperrliste vormerken (nutzt bestehende Infrastruktur aus blocklist_update.php) $blk = $pdo->prepare("INSERT INTO phplist_user_user_attribute (userid, attributeid, value) VALUES (:uid, :aid, 'on') ON DUPLICATE KEY UPDATE value = 'on'"); $blk->execute(['uid' => $c['id'], 'aid' => $attrIpBlockId]); // 3. Nur die IP an SFS melden - NICHT die moeglicherweise fremde E-Mail-Adresse $data = http_build_query([ 'ip_addr' => $c['conf_ip'], 'username' => 'blitzbestaetigung-bot', 'api_key' => $sfsApiKey, 'evidence' => "Automatisiert erkannt: Bestaetigung nach nur {$c['diff_seconds']}s von abweichender IP (Anmelde-IP: {$c['sub_ip']})", ]); $ch = curl_init('https://www.stopforumspam.com/add.php'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_exec($ch); curl_close($ch); // 4. Als bearbeitet markieren (Duplikatschutz) $mark = $pdo->prepare("INSERT INTO phplist_user_user_attribute (userid, attributeid, value) VALUES (:uid, :aid, 'on') ON DUPLICATE KEY UPDATE value = 'on'"); $mark->execute(['uid' => $c['id'], 'aid' => $attrBlitzId]); echo "Zurueckgesetzt & IP vorgemerkt: userid {$c['id']} ({$c['diff_seconds']}s, sub_ip: {$c['sub_ip']}, conf_ip: {$c['conf_ip']})\n"; sleep(1); }