Erweiterte Spamschutz-Maßnahmen für Kontaktformular
- Honeypot-Feld zur Bot-Erkennung hinzugefügt - Zeitbasierte Validierung (min. 3 Sek., max. 1 Std.) - IP-basiertes Rate-Limiting (3 Anfragen/Stunde) - Erweiterte Spam-Mustererkennung (URLs, Keywords, etc.) - Referrer-Validierung auf PHP- und .htaccess-Ebene - E-Mail-Domain-Prüfung gegen Wegwerf-Adressen - Nachrichten-Längenvalidierung (10-5000 Zeichen) - .htaccess-Schutz gegen Bot-User-Agents und verdächtige HTTP-Methoden
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
Version: 4.7.1 (03.02.2026)
|
||||
- Erweiterte Spamschutz-Maßnahmen für Kontaktformular:
|
||||
* Honeypot-Feld zur Bot-Erkennung
|
||||
* Zeitbasierte Validierung (min. 3 Sek., max. 1 Std.)
|
||||
* IP-basiertes Rate-Limiting (3 Anfragen/Stunde)
|
||||
* Erweiterte Spam-Mustererkennung (URLs, Keywords, etc.)
|
||||
* Referrer-Validierung
|
||||
* E-Mail-Domain-Prüfung gegen Wegwerf-Adressen
|
||||
* Nachrichten-Längenvalidierung (10-5000 Zeichen)
|
||||
* .htaccess-Schutz gegen Bots und direkte Aufrufe
|
||||
|
||||
Version: 4.7.0
|
||||
- Updated Bootstrap to version 5.1.3
|
||||
- Updated all outdated third party vendor libraries to their latest versions
|
||||
|
||||
@@ -16,3 +16,25 @@ Options -Indexes
|
||||
<FilesMatch "\.(bak|backup|old|temp|tmp|swp|~)$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# Rate-Limiting für contact.php
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Blockiere bekannte Spam-User-Agents
|
||||
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
|
||||
RewriteCond %{HTTP_USER_AGENT} (bot|crawler|spider|scraper|harvester|curl|wget|python-requests) [NC]
|
||||
RewriteRule ^contact\.php$ - [F,L]
|
||||
|
||||
# Blockiere direkte Aufrufe ohne Referrer (außer von eigener Domain)
|
||||
RewriteCond %{REQUEST_URI} ^/forms/contact\.php$ [NC]
|
||||
RewriteCond %{HTTP_REFERER} !^$
|
||||
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?webfarben\.net [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# Blockiere verdächtige Request-Methoden
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
</IfModule>
|
||||
|
||||
@@ -24,6 +24,73 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Spam-Schutz: Honeypot-Prüfung
|
||||
if (!empty($_POST['website'])) {
|
||||
// Bot hat das Honeypot-Feld ausgefüllt
|
||||
echo json_encode(['status' => 'error', 'message' => 'Spam erkannt']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Spam-Schutz: Zeitbasierte Validierung (mindestens 3 Sekunden)
|
||||
if (isset($_POST['form_timestamp'])) {
|
||||
$formTimestamp = intval($_POST['form_timestamp']);
|
||||
$currentTime = time() * 1000; // Millisekunden
|
||||
$timeDiff = ($currentTime - $formTimestamp) / 1000; // Sekunden
|
||||
|
||||
if ($timeDiff < 3) {
|
||||
// Formular wurde zu schnell abgeschickt (Bot)
|
||||
echo json_encode(['status' => 'error', 'message' => 'Bitte warten Sie einen Moment vor dem Absenden']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($timeDiff > 3600) {
|
||||
// Formular ist zu alt (über 1 Stunde)
|
||||
echo json_encode(['status' => 'error', 'message' => 'Formular-Session abgelaufen. Bitte laden Sie die Seite neu']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Spam-Schutz: IP-basiertes Rate-Limiting
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$rateLimit = 3; // Maximale Anfragen
|
||||
$timeWindow = 3600; // Zeitfenster in Sekunden (1 Stunde)
|
||||
$rateLimitFile = sys_get_temp_dir() . '/contact_rate_limit_' . md5($ip) . '.txt';
|
||||
|
||||
if (file_exists($rateLimitFile)) {
|
||||
$data = json_decode(file_get_contents($rateLimitFile), true);
|
||||
$attempts = $data['attempts'] ?? 0;
|
||||
$firstAttempt = $data['first_attempt'] ?? time();
|
||||
|
||||
// Prüfe ob Zeitfenster abgelaufen ist
|
||||
if (time() - $firstAttempt < $timeWindow) {
|
||||
if ($attempts >= $rateLimit) {
|
||||
echo json_encode(['status' => 'error', 'message' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut']);
|
||||
exit;
|
||||
}
|
||||
// Erhöhe Zähler
|
||||
$data['attempts'] = $attempts + 1;
|
||||
} else {
|
||||
// Zeitfenster abgelaufen, reset
|
||||
$data = ['attempts' => 1, 'first_attempt' => time()];
|
||||
}
|
||||
} else {
|
||||
// Erste Anfrage von dieser IP
|
||||
$data = ['attempts' => 1, 'first_attempt' => time()];
|
||||
}
|
||||
|
||||
file_put_contents($rateLimitFile, json_encode($data));
|
||||
|
||||
// Spam-Schutz: Referrer-Prüfung
|
||||
if (!empty($_SERVER['HTTP_REFERER'])) {
|
||||
$referer = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
|
||||
$allowedHosts = ['webfarben.net', 'www.webfarben.net', 'localhost'];
|
||||
|
||||
if (!in_array($referer, $allowedHosts)) {
|
||||
echo json_encode(['status' => 'error', 'message' => 'Ungültige Anfrage-Quelle']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// POST-Daten prüfen und bereinigen
|
||||
$name = isset($_POST['name']) ? trim(htmlspecialchars($_POST['name'])) : '';
|
||||
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
|
||||
@@ -49,6 +116,72 @@ if (empty($message)) {
|
||||
$errors[] = 'Nachricht ist erforderlich';
|
||||
}
|
||||
|
||||
// Spam-Schutz: Inhaltsvalidierung
|
||||
function containsSpamPatterns($text) {
|
||||
// Prüfe auf zu viele URLs
|
||||
$urlCount = preg_match_all('/https?:\/\/[^\s]+/i', $text, $matches);
|
||||
if ($urlCount > 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prüfe auf verdächtige Spam-Begriffe
|
||||
$spamKeywords = [
|
||||
'viagra', 'cialis', 'casino', 'poker', 'lottery',
|
||||
'crypto', 'bitcoin', 'investment', 'forex', 'loan',
|
||||
'weight loss', 'diet pills', 'replica', 'rolex',
|
||||
'click here', 'buy now', 'limited offer', 'act now',
|
||||
'congratulations', 'you won', 'claim your prize',
|
||||
'enlargement', 'pharmacy', 'prescription'
|
||||
];
|
||||
|
||||
$lowerText = strtolower($text);
|
||||
foreach ($spamKeywords as $keyword) {
|
||||
if (strpos($lowerText, $keyword) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Prüfe auf zu viele Großbuchstaben (mehr als 50%)
|
||||
$upperCount = preg_match_all('/[A-Z]/', $text);
|
||||
$letterCount = preg_match_all('/[A-Za-z]/', $text);
|
||||
if ($letterCount > 10 && ($upperCount / $letterCount) > 0.5) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Prüfe auf verdächtig viele gleiche Zeichen hintereinander
|
||||
if (preg_match('/(.)\1{10,}/', $text)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validiere Nachricht und Betreff auf Spam-Muster
|
||||
if (containsSpamPatterns($message) || containsSpamPatterns($subject)) {
|
||||
$errors[] = 'Ihre Nachricht enthält unzulässige Inhalte';
|
||||
}
|
||||
|
||||
// Prüfe auf verdächtige E-Mail-Domains
|
||||
$emailDomain = substr(strrchr($email, "@"), 1);
|
||||
$suspiciousDomains = [
|
||||
'tempmail.com', 'throwaway.email', '10minutemail.com',
|
||||
'guerrillamail.com', 'mailinator.com', 'maildrop.cc'
|
||||
];
|
||||
|
||||
if (in_array(strtolower($emailDomain), $suspiciousDomains)) {
|
||||
$errors[] = 'Bitte verwenden Sie eine gültige E-Mail-Adresse';
|
||||
}
|
||||
|
||||
// Prüfe auf minimale Nachrichtenlänge
|
||||
if (strlen($message) < 10) {
|
||||
$errors[] = 'Die Nachricht ist zu kurz (mindestens 10 Zeichen)';
|
||||
}
|
||||
|
||||
// Prüfe auf maximale Nachrichtenlänge
|
||||
if (strlen($message) > 5000) {
|
||||
$errors[] = 'Die Nachricht ist zu lang (maximal 5000 Zeichen)';
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
echo json_encode(['status' => 'error', 'message' => implode(', ', $errors)]);
|
||||
exit;
|
||||
|
||||
11
index.html
11
index.html
@@ -716,6 +716,10 @@
|
||||
<div class="col-lg-8 mt-5 mt-lg-0">
|
||||
|
||||
<form action="forms/contact.php" method="post" role="form" class="php-email-form">
|
||||
<!-- Honeypot-Feld (versteckt, nur für Bots sichtbar) -->
|
||||
<input type="text" name="website" style="display:none !important" tabindex="-1" autocomplete="off">
|
||||
<!-- Zeitstempel für Spam-Schutz -->
|
||||
<input type="hidden" name="form_timestamp" value="">
|
||||
<div class="row">
|
||||
<div class="col-md-6 form-group">
|
||||
<input type="text" name="name" class="form-control" id="name" placeholder="Your Name" required>
|
||||
@@ -738,6 +742,13 @@
|
||||
<div class="text-center"><button type="submit">Send Message</button></div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// Setze Zeitstempel wenn Formular geladen wird
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelector('input[name="form_timestamp"]').value = Date.now();
|
||||
});
|
||||
</script>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user