WBCE CMS – Way Better Content Editing.
You are not logged in.
Pages: 1
Moin!
Heutzutage sind die "unerwünschten Gäste" einer Webseite schon die Regel.
Ihre Webseitenaufrufe veränderen unter anderem die eigentliche Besucherstatistik. Man kann bestimmte URI´s sperren und damit auch deren Aufrufe in der Statistik. Die normale Aufrufe (sprich von den existierenden Seiten) werden aber weiter auch von diesen "Besucher" gezählt.
In diesem Zusammenhabf ist mir eine Frage aufgefallen.
Wäre es irgendwie möglich nach Aufruf einer URI mit bestimmten Wörter (Zeichenkomnination) die IP-Adresse des Benutzers für eine bestimmte Zeit sperren?
So was, wie bei mehreren Versuchen die falschen Logindaten einzugeben wird die IP-Adresse für eine bestimmte Zeit gesperret.
Offline
Interessante Idee, ich kenne das von Wordfence (einem Plugin für Würgpress).
Sprich doch mal Ruud direkt darauf an. Sein 404-Modul loggt bereits verdächtige Anfragen, vielleicht lässt sich das entsprechend erweitern.
Ruud freut sich übrigens auch über Nutzung seines Paypal-Spendenlinks.
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Für den Backend-Login ist ja schon eine IP-basierte Sperre drin, die bei Fehlversuchen einen Timeout hoch setzt.
Aber diese IPs dann für den Aufruf beliebiger Seiten auch sprren zu können, wäre eine interessante Erweiterung.
Das müsste man vermutlich in der Frontend-Klasse mit verdrahten, und für diese gesperrten IPs halt einen 401 Status code ausgeben.
Offline
Moin!
Ich habe an einer Lösung gebastellt und scheinbar eine funktionierende Methode gefunden.
Es sind zwei neue Dateien, die im root der WBCE-Installation platziert sollen:
1. security_check.php - die ist für Sperrung
2. banned_ips.json - da werden die gesperrten IP-Adressen provisorisch gespeichert.
security_check.php:
[== PHP ==]
<?php
// Datei: security_check.php
// Einstellungen
$forbiddenPatterns = ['/test123/', '/hack/', '/badword/']; // Verbotene Muster (Regex)
$banDuration = 60; // Sperrdauer in Sekunden (z. B. 60 s =1 Minute)
// Funktion, um die IP-Adresse des Besuchers zu ermitteln
function getVisitorIP() {
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
// Funktion, um eine IP-Adresse zu sperren
function banIP($ip, $duration) {
$bannedIPsFile = 'banned_ips.json'; // Datei zur Speicherung der gesperrten IPs
$bannedIPs = [];
// Lade bestehende Sperren
if (file_exists($bannedIPsFile)) {
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
}
// Füge die aktuelle Sperre hinzu
$bannedIPs[$ip] = time() + $duration;
// Speichere die Sperren zurück in die Datei
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
}
// Funktion, um zu prüfen, ob eine IP gesperrt ist
function isIPBanned($ip) {
$bannedIPsFile = 'banned_ips.json'; // Datei zur Speicherung der gesperrten IPs
if (!file_exists($bannedIPsFile)) {
return false;
}
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
// Entferne abgelaufene Sperren
$currentTime = time();
foreach ($bannedIPs as $bannedIP => $expiry) {
if ($expiry < $currentTime) {
unset($bannedIPs[$bannedIP]);
}
}
// Aktualisierte Liste speichern
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
return isset($bannedIPs[$ip]);
}
// Hauptlogik
$visitorIP = getVisitorIP();
$requestURI = $_SERVER['REQUEST_URI'] ?? '/';
if (isIPBanned($visitorIP)) {
// Sperrmeldung anzeigen und Zugriff blockieren
http_response_code(403);
die('Zugriff verweigert. Ihre IP-Adresse wurde gesperrt.');
}
// Überprüfe, ob die URI verbotene Muster enthält
foreach ($forbiddenPatterns as $pattern) {
if (preg_match($pattern, $requestURI)) {
// IP-Adresse sperren
banIP($visitorIP, $banDuration);
// Sperrmeldung anzeigen
http_response_code(403);
die('Verbotenes Muster erkannt. Ihre IP-Adresse wurde gesperrt.');
}
}
?>
In der Datei index.php im root Verzeichnis der WBCE-Installation gleich am Anfang der Code nach <?php folgende Zeile einfügen:
[== PHP ==]
include 'security_check.php'; // Schutz für alle Seiten
Die verbotene Zeichenkombinationen sowie die Sperrzeit werden gleich am Anfang der Datei security_check.php definiert:
// Einstellungen
$forbiddenPatterns = ['/test123/', '/hack/', '/badword/']; // Verbotene Muster (Regex)
$banDuration = 60; // Sperrdauer in Sekunden (z. B. 1 Stunde)
Die Meldung, die bei der Sperrung angezeigt wird, kann am Ende der selben Datei definiert werden:
// Sperrmeldung anzeigen
http_response_code(403);
die('Verbotenes Muster erkannt. Ihre IP-Adresse wurde gesperrt.');
Um die vorgeschlagene Lösung zu testen:
Besuche die Webseite mit erlaubten URLs, um sicherzustellen, dass der Zugriff funktioniert.
Greife mit einer verbotenen Zeichenkombination in der URL zu (z. B. /index.php?test123), um zu prüfen, ob die Sperrung funktioniert.
Warte die Sperrdauer ab und prüfe, ob die IP-Adresse nach Ablauf wieder Zugriff hat.
Vielleicht kann man daraus ein WBCE-Modul basteln...
Offline
Ich habe es mir überlegt, die Vorgehensweise etwas zu erweitern.
Die "fleißigen" unerwünschten Besucher rufen oft in sekundenschnelle mehrere UPI´s. Ein „normaler“ Mensch kann so was nicht.
Man kann versuchen durch die „Häufigkeitsbegrenzung“ auch solche Besucher sperren.
Um die oben vorgeschlagene Lösung zu ergänzen erstelle ich noch eine Datei Namens rate_limit.json im root Verzeichnis
Alle Einstellungen (auch die Fehlermeldungtexte) habe ich zur besseren Übersicht oben bei den Einstellungen gruppiert.
Hier ist die dafür der angepasste Code der Datei security_check.php:
[== PHP ==]
<?php
// Einstellungen
$forbiddenPatterns = ['/test123/', '/hack/', '/badword/']; // Verbotene Muster (Regex)
$banDuration = 30; // Sperrdauer in Sekunden (z. B. 60 = 1 Minute, 3600 = 1 Stunde)
$rateLimit = 3; // Maximale Anfragen pro Zeitfenster
$rateLimitWindow = 3; // Zeitfenster in Sekunden (z. B. 60 = 1 Minute, 3600 = 1 Stunde)
// Fehlermeldungen
$errorMessages = [
'banned' => 'Zugriff verweigert. Ihre IP-Adresse wurde gesperrt.',
'rate_limit' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.',
'forbidden_pattern' => 'Verbotenes Muster erkannt. Ihre IP-Adresse wurde gesperrt.'
];
// Dateien zur Speicherung von Sperren und Limits
$bannedIPsFile = 'banned_ips.json'; // Datei zur Speicherung der gesperrten IPs
$rateLimitFile = 'rate_limit.json'; // Datei zur Speicherung der Anfrage-Zähler
// Funktion, um die IP-Adresse des Besuchers zu ermitteln
function getVisitorIP() {
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
// Funktion, um eine IP-Adresse zu sperren
function banIP($ip, $duration) {
global $bannedIPsFile;
$bannedIPs = [];
if (file_exists($bannedIPsFile)) {
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
}
$bannedIPs[$ip] = time() + $duration;
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
}
// Funktion, um zu prüfen, ob eine IP gesperrt ist
function isIPBanned($ip) {
global $bannedIPsFile;
if (!file_exists($bannedIPsFile)) {
return false;
}
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
$currentTime = time();
// Entferne abgelaufene Sperren
foreach ($bannedIPs as $bannedIP => $expiry) {
if ($expiry < $currentTime) {
unset($bannedIPs[$bannedIP]);
}
}
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
return isset($bannedIPs[$ip]);
}
// Funktion, um die Häufigkeitsbegrenzung zu überprüfen
function checkRateLimit($ip) {
global $rateLimit, $rateLimitWindow, $rateLimitFile;
$rateData = [];
if (file_exists($rateLimitFile)) {
$rateData = json_decode(file_get_contents($rateLimitFile), true);
}
$currentTime = time();
// Entferne veraltete Einträge
foreach ($rateData as $ipAddress => $data) {
if ($data['timestamp'] + $rateLimitWindow < $currentTime) {
unset($rateData[$ipAddress]);
}
}
// Aktualisiere die Daten für die aktuelle IP
if (!isset($rateData[$ip])) {
$rateData[$ip] = ['count' => 1, 'timestamp' => $currentTime];
} else {
$rateData[$ip]['count'] += 1;
}
// Sperre die IP, wenn das Limit überschritten wurde
if ($rateData[$ip]['count'] > $rateLimit) {
file_put_contents($rateLimitFile, json_encode($rateData)); // Daten speichern
return false; // Limit überschritten
}
file_put_contents($rateLimitFile, json_encode($rateData)); // Daten speichern
return true;
}
// Hauptlogik
$visitorIP = getVisitorIP();
$requestURI = $_SERVER['REQUEST_URI'] ?? '/';
// Prüfen, ob die IP bereits gesperrt ist
if (isIPBanned($visitorIP)) {
http_response_code(403);
die($errorMessages['banned']);
}
// Häufigkeitsbegrenzung überprüfen
if (!checkRateLimit($visitorIP)) {
http_response_code(429); // 429 Too Many Requests
die($errorMessages['rate_limit']);
}
// Überprüfen auf verbotene Muster in der URI
foreach ($forbiddenPatterns as $pattern) {
if (preg_match($pattern, $requestURI)) {
// IP-Adresse sperren
banIP($visitorIP, $banDuration);
http_response_code(403);
die($errorMessages['forbidden_pattern']);
}
}
?>
Last edited by kleo (05.12.2024 13:42:01)
Offline
Und noch eine Erweiterung.
Wenn der gesperrte Besucher innerhalb der Sperrzeit erneut die Webseite aufruft, wird die Sperrzeit neu gesetzt:
[== PHP ==]
<?php
// Einstellungen
$forbiddenPatterns = ['/adminer/', '/test123/', '/badword/']; // Verbotene Muster (Regex)
$banDuration = 10; // Sperrdauer in Sekunden (z. B. 60 = 1 Minute, 3600 = 1 Stunde)
$rateLimit = 3; // Maximale Anfragen pro Zeitfenster
$rateLimitWindow = 3; // Zeitfenster in Sekunden (z. B. 60 = 1 Minute, 3600 = 1 Stunde)
// Fehlermeldungen
$errorMessages = [
'banned' => 'Zugriff verweigert.',
'rate_limit' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.',
'forbidden_pattern' => 'Zugriff verweigert.'
];
// Dateien zur Speicherung von Sperren und Limits
$bannedIPsFile = 'banned_ips.json'; // Datei zur Speicherung der gesperrten IPs
$rateLimitFile = 'rate_limit.json'; // Datei zur Speicherung der Anfrage-Zähler
// Funktion, um die IP-Adresse des Besuchers zu ermitteln
function getVisitorIP() {
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
// Funktion, um eine IP-Adresse zu sperren
function banIP($ip, $duration) {
global $bannedIPsFile;
$bannedIPs = [];
if (file_exists($bannedIPsFile)) {
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
}
// Setze die neue Sperrzeit
$bannedIPs[$ip] = time() + $duration;
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
}
// Funktion, um zu prüfen, ob eine IP gesperrt ist und ggf. die Sperrzeit zu verlängern
function isIPBanned($ip) {
global $bannedIPsFile, $banDuration;
if (!file_exists($bannedIPsFile)) {
return false;
}
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
$currentTime = time();
// Entferne abgelaufene Sperren
foreach ($bannedIPs as $bannedIP => $expiry) {
if ($expiry < $currentTime) {
unset($bannedIPs[$bannedIP]);
}
}
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
// Falls die IP gesperrt ist, verlängere die Sperrzeit
if (isset($bannedIPs[$ip])) {
banIP($ip, $banDuration); // Sperrzeit zurücksetzen
return true;
}
return false;
}
// Funktion, um die Häufigkeitsbegrenzung zu überprüfen
function checkRateLimit($ip) {
global $rateLimit, $rateLimitWindow, $rateLimitFile;
$rateData = [];
if (file_exists($rateLimitFile)) {
$rateData = json_decode(file_get_contents($rateLimitFile), true);
}
$currentTime = time();
// Entferne veraltete Einträge
foreach ($rateData as $ipAddress => $data) {
if ($data['timestamp'] + $rateLimitWindow < $currentTime) {
unset($rateData[$ipAddress]);
}
}
// Aktualisiere die Daten für die aktuelle IP
if (!isset($rateData[$ip])) {
$rateData[$ip] = ['count' => 1, 'timestamp' => $currentTime];
} else {
$rateData[$ip]['count'] += 1;
}
// Sperre die IP, wenn das Limit überschritten wurde
if ($rateData[$ip]['count'] > $rateLimit) {
file_put_contents($rateLimitFile, json_encode($rateData)); // Daten speichern
return false; // Limit überschritten
}
file_put_contents($rateLimitFile, json_encode($rateData)); // Daten speichern
return true;
}
// Hauptlogik
$visitorIP = getVisitorIP();
$requestURI = $_SERVER['REQUEST_URI'] ?? '/';
// Prüfen, ob die IP bereits gesperrt ist
if (isIPBanned($visitorIP)) {
http_response_code(403);
die($errorMessages['banned']);
}
// Häufigkeitsbegrenzung überprüfen
if (!checkRateLimit($visitorIP)) {
http_response_code(429); // 429 Too Many Requests
die($errorMessages['rate_limit']);
}
// Überprüfen auf verbotene Muster in der URI
foreach ($forbiddenPatterns as $pattern) {
if (preg_match($pattern, $requestURI)) {
// IP-Adresse sperren
banIP($visitorIP, $banDuration);
http_response_code(403);
die($errorMessages['forbidden_pattern']);
}
}
?>
Offline
Verbotenes Muster erkannt. Ihre IP-Adresse wurde gesperrt
Ich würde das "Verbotene Muster" einfach weglassen.
Offline
Die Fehlermeldungen kann man frei definieren. Und wenn man will, auch in verschiedenen Sprachen.
Man kann auch ein Bild an der Stelle von Textmeldungen zeigen.
Es ist zu überlegen, ob durch die "Häufigkeitsbegrenzung" nicht die Suchmaschinen bei Ihrer Arbeit gehindert werden.
Ich habe keine Ahnung, wie schnell die Suchmaschinen-Crawler einzelne Aufrufe tätigen.
Vielleicht kann man da durch eine bestimmte Einstellung für maximale Anzahl der Anfragen pro Zeitfenster regeln.
Eine andere Überlegung:
die beiden Dateien banned_ips.json und rate_limit.json mittels .htaccess von fremden Ansehen zu schützen.
Am besten wäre vielleicht ein Modul daraus zu erstellen.
Ich glaube aber nicht, dass ich es alleine schaffe...
Offline
Seriöse Suchmaschinen kann man erkennen und ausnehmen.
Ich habe eine Amazon-Wishlist. Oder spende an das Projekt.
Ich kann, wenn ich will, aber wer will, dass ich muss, kann mich mal
Online
Hi Webbird,
danke für den Tipp.
Ich habe weiter gebastellt und der Code mit der Suchmaschinen Erkennung ergänzt.
Hier ist es zum Testen:
[== PHP ==]
<?php
// Einstellungen
$forbiddenPatterns = ['/adminer/', '/test123/', '/badword/']; // Verbotene Muster (Regex)
$banDuration = 10; // Sperrdauer in Sekunden (z. B. 60 = 1 Minute, 3600 = 1 Stunde)
$rateLimit = 3; // Maximale Anfragen pro Zeitfenster
$rateLimitWindow = 1; // Zeitfenster in Sekunden (z. B. 60 = 1 Minute, 3600 = 1 Stunde)
// Fehlermeldungen
$errorMessages = [
'banned' => 'Zugriff verweigert.',
'rate_limit' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.',
'forbidden_pattern' => 'Zugriff verweigert.'
];
// Suchmaschinen-Roboter-User-Agents
$searchEngineBots = [
'Googlebot',
'Bingbot',
'Slurp', // Yahoo
'DuckDuckBot',
'Baiduspider',
'YandexBot',
'Sogou',
'Exabot',
'facebot',
'ia_archiver' // Alexa Crawler
];
// Dateien zur Speicherung von Sperren und Limits
$bannedIPsFile = 'banned_ips.json'; // Datei zur Speicherung der gesperrten IPs
$rateLimitFile = 'rate_limit.json'; // Datei zur Speicherung der Anfrage-Zähler
// Funktion, um die IP-Adresse des Besuchers zu ermitteln
function getVisitorIP() {
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
// Funktion, um zu prüfen, ob der aktuelle User-Agent ein Suchmaschinen-Bot ist
function isSearchEngineBot($userAgent, $bots) {
foreach ($bots as $bot) {
if (stripos($userAgent, $bot) !== false) {
return true;
}
}
return false;
}
// Funktion, um eine IP-Adresse zu sperren
function banIP($ip, $duration) {
global $bannedIPsFile;
$bannedIPs = [];
if (file_exists($bannedIPsFile)) {
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
}
// Setze die neue Sperrzeit
$bannedIPs[$ip] = time() + $duration;
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
}
// Funktion, um zu prüfen, ob eine IP gesperrt ist und ggf. die Sperrzeit zu verlängern
function isIPBanned($ip) {
global $bannedIPsFile, $banDuration;
if (!file_exists($bannedIPsFile)) {
return false;
}
$bannedIPs = json_decode(file_get_contents($bannedIPsFile), true);
$currentTime = time();
// Entferne abgelaufene Sperren
foreach ($bannedIPs as $bannedIP => $expiry) {
if ($expiry < $currentTime) {
unset($bannedIPs[$bannedIP]);
}
}
file_put_contents($bannedIPsFile, json_encode($bannedIPs));
// Falls die IP gesperrt ist, verlängere die Sperrzeit
if (isset($bannedIPs[$ip])) {
banIP($ip, $banDuration); // Sperrzeit zurücksetzen
return true;
}
return false;
}
// Funktion, um die Häufigkeitsbegrenzung zu überprüfen
function checkRateLimit($ip) {
global $rateLimit, $rateLimitWindow, $rateLimitFile;
$rateData = [];
if (file_exists($rateLimitFile)) {
$rateData = json_decode(file_get_contents($rateLimitFile), true);
}
$currentTime = time();
// Entferne veraltete Einträge
foreach ($rateData as $ipAddress => $data) {
if ($data['timestamp'] + $rateLimitWindow < $currentTime) {
unset($rateData[$ipAddress]);
}
}
// Aktualisiere die Daten für die aktuelle IP
if (!isset($rateData[$ip])) {
$rateData[$ip] = ['count' => 1, 'timestamp' => $currentTime];
} else {
$rateData[$ip]['count'] += 1;
}
// Sperre die IP, wenn das Limit überschritten wurde
if ($rateData[$ip]['count'] > $rateLimit) {
file_put_contents($rateLimitFile, json_encode($rateData)); // Daten speichern
return false; // Limit überschritten
}
file_put_contents($rateLimitFile, json_encode($rateData)); // Daten speichern
return true;
}
// Hauptlogik
$visitorIP = getVisitorIP();
$requestURI = $_SERVER['REQUEST_URI'] ?? '/';
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
// Prüfen, ob der Besucher ein Suchmaschinen-Bot ist
if (isSearchEngineBot($userAgent, $searchEngineBots)) {
echo "Suchmaschinen-Bot erkannt. Keine Begrenzung angewendet.";
exit;
}
// Prüfen, ob die IP bereits gesperrt ist
if (isIPBanned($visitorIP)) {
http_response_code(403);
die($errorMessages['banned']);
}
// Häufigkeitsbegrenzung überprüfen
if (!checkRateLimit($visitorIP)) {
http_response_code(429); // 429 Too Many Requests
die($errorMessages['rate_limit']);
}
// Überprüfen auf verbotene Muster in der URI
foreach ($forbiddenPatterns as $pattern) {
if (preg_match($pattern, $requestURI)) {
// IP-Adresse sperren
banIP($visitorIP, $banDuration);
http_response_code(403);
die($errorMessages['forbidden_pattern']);
}
}
?>
Ich habe hier zum Testen die Sperrdauer auf 10 Sekunden eingestellt, normal würde ich sie wahrscheinlich mindestens auf 1 Stunde setzen.
Last edited by kleo (05.12.2024 13:41:10)
Offline
Pages: 1