Files
phpList-Bot-Schutz/blitzbestaetigung_process.php
T

89 lines
4.0 KiB
PHP
Raw Normal View History

2026-08-28 18:47:22 +02:00
<?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);
}