Implement comprehensive spam protection for contact forms

- Add CSRF protection to quote form
- Add honeypot fields to both forms
- Expand spam keyword detection (25+ terms)
- Implement bot detection (user agent & timing validation)
- Add IP-based blocking system (24-hour blocks)
- Enhanced content filtering and validation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Peter
2025-06-17 18:43:06 +01:00
parent 47345e5849
commit 7e69cd0c19
3 changed files with 888 additions and 743 deletions

View File

@@ -112,6 +112,32 @@ if (!$referer_valid && !isset($_SERVER['HTTP_REFERER'])) {
error_log("Contact form accessed without referer from IP: " . $_SERVER['REMOTE_ADDR']);
}
// Check for blocked IPs
function checkBlockedIP() {
$ip = $_SERVER['REMOTE_ADDR'];
$blockFile = 'logs/blocked-ips.txt';
if (file_exists($blockFile)) {
$blockedIPs = file($blockFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($blockedIPs as $blockedEntry) {
$parts = explode('|', $blockedEntry);
if (isset($parts[0]) && $parts[0] === $ip) {
$blockTime = isset($parts[1]) ? (int)$parts[1] : 0;
// Block for 24 hours
if (time() - $blockTime < 86400) {
return false;
}
}
}
}
return true;
}
// Check for blocked IPs first
if (!checkBlockedIP()) {
sendResponse(false, 'Access temporarily restricted');
}
// Check rate limiting
if (!checkRateLimit()) {
sendResponse(false, 'Too many requests. Please try again later.');
@@ -149,16 +175,42 @@ if (isset($_POST['website']) && !empty($_POST['website'])) {
sendResponse(false, 'Spam detected');
}
// Check for spam keywords
$spamKeywords = ['viagra', 'casino', 'lottery', 'bitcoin', 'forex', 'loan', 'debt', 'pharmacy'];
$messageContent = strtolower($message . ' ' . $name . ' ' . $company);
// Enhanced spam protection - expanded keyword list
$spamKeywords = [
'viagra', 'cialis', 'casino', 'lottery', 'bitcoin', 'forex', 'loan', 'debt',
'pharmacy', 'click here', 'act now', 'limited time', 'risk free', 'guarantee',
'no obligation', 'free money', 'make money fast', 'work from home', 'get rich',
'investment opportunity', 'credit repair', 'refinance', 'consolidate debt',
'weight loss', 'miracle cure', 'lose weight', 'adult content', 'porn',
'sex', 'dating', 'singles', 'webcam', 'escort', 'massage'
];
$messageContent = strtolower($message . ' ' . $name . ' ' . $company);
foreach ($spamKeywords as $keyword) {
if (strpos($messageContent, $keyword) !== false) {
sendResponse(false, 'Invalid content detected');
}
}
// Bot detection - check for suspicious patterns
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$suspiciousAgents = ['curl', 'wget', 'python', 'bot', 'crawler', 'spider', 'scraper'];
foreach ($suspiciousAgents as $agent) {
if (stripos($userAgent, $agent) !== false) {
sendResponse(false, 'Automated submissions not allowed');
}
}
// Check submission speed (too fast = likely bot)
if (!isset($_SESSION['form_start_time'])) {
$_SESSION['form_start_time'] = time();
}
$submissionTime = time() - $_SESSION['form_start_time'];
if ($submissionTime < 5) { // Less than 5 seconds to fill form
sendResponse(false, 'Form submitted too quickly');
}
// Update rate limit counter
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'contact_' . md5($ip);

View File

@@ -8,6 +8,18 @@ header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
header('Content-Type: application/json');
// CSRF Protection
function generateCSRFToken() {
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
function validateCSRFToken($token) {
return isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
}
// Rate limiting
function checkRateLimit() {
$ip = $_SERVER['REMOTE_ADDR'];
@@ -71,11 +83,47 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
sendResponse(false, 'Invalid request method');
}
// Validate CSRF token
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
sendResponse(false, 'Security validation failed. Please refresh the page and try again.');
}
// Check for blocked IPs
function checkBlockedIP() {
$ip = $_SERVER['REMOTE_ADDR'];
$blockFile = 'logs/blocked-ips.txt';
if (file_exists($blockFile)) {
$blockedIPs = file($blockFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($blockedIPs as $blockedEntry) {
$parts = explode('|', $blockedEntry);
if (isset($parts[0]) && $parts[0] === $ip) {
$blockTime = isset($parts[1]) ? (int)$parts[1] : 0;
// Block for 24 hours
if (time() - $blockTime < 86400) {
return false;
}
}
}
}
return true;
}
// Check for blocked IPs first
if (!checkBlockedIP()) {
sendResponse(false, 'Access temporarily restricted');
}
// Check rate limiting
if (!checkRateLimit()) {
sendResponse(false, 'Too many requests. Please try again later.');
}
// Spam protection - honeypot field
if (isset($_POST['website']) && !empty($_POST['website'])) {
sendResponse(false, 'Spam detected');
}
// Validate and sanitize inputs
$services = $_POST['services'] ?? [];
$project_scale = validateInput($_POST['project_scale'] ?? '', 'text');
@@ -119,6 +167,42 @@ if (!empty($errors)) {
sendResponse(false, implode('. ', $errors));
}
// Enhanced spam protection - content filtering
$spamKeywords = [
'viagra', 'cialis', 'casino', 'lottery', 'bitcoin', 'forex', 'loan', 'debt',
'pharmacy', 'click here', 'act now', 'limited time', 'risk free', 'guarantee',
'no obligation', 'free money', 'make money fast', 'work from home', 'get rich',
'investment opportunity', 'credit repair', 'refinance', 'consolidate debt',
'weight loss', 'miracle cure', 'lose weight', 'adult content', 'porn',
'sex', 'dating', 'singles', 'webcam', 'escort', 'massage'
];
$contentToCheck = strtolower($requirements . ' ' . $name . ' ' . $company . ' ' . $data_sources);
foreach ($spamKeywords as $keyword) {
if (strpos($contentToCheck, $keyword) !== false) {
sendResponse(false, 'Invalid content detected');
}
}
// Bot detection - check for suspicious patterns
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$suspiciousAgents = ['curl', 'wget', 'python', 'bot', 'crawler', 'spider', 'scraper'];
foreach ($suspiciousAgents as $agent) {
if (stripos($userAgent, $agent) !== false) {
sendResponse(false, 'Automated submissions not allowed');
}
}
// Check submission speed (too fast = likely bot)
if (!isset($_SESSION['form_start_time'])) {
$_SESSION['form_start_time'] = time();
}
$submissionTime = time() - $_SESSION['form_start_time'];
if ($submissionTime < 10) { // Less than 10 seconds for quote form (more complex)
sendResponse(false, 'Form submitted too quickly');
}
// Sanitize services array
$services = array_map(function($service) {
return htmlspecialchars(trim($service), ENT_QUOTES, 'UTF-8');

1489
quote.php

File diff suppressed because it is too large Load Diff