This commit is contained in:
Peter
2025-06-17 19:22:58 +01:00
parent 623b29dea4
commit 283ea68ff8
6 changed files with 574 additions and 24 deletions

View File

@@ -2,6 +2,9 @@
// Enhanced Contact Form Handler with Security
session_start();
// Include reCAPTCHA config
require_once '.recaptcha-config.php';
// Security headers
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
@@ -143,6 +146,54 @@ if (!checkRateLimit()) {
sendResponse(false, 'Too many requests. Please try again later.');
}
// Verify reCAPTCHA v3
if (isset($_POST['recaptcha_response'])) {
$recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
$recaptcha_secret = RECAPTCHA_SECRET_KEY;
$recaptcha_response = $_POST['recaptcha_response'];
$recaptcha_data = array(
'secret' => $recaptcha_secret,
'response' => $recaptcha_response,
'remoteip' => $_SERVER['REMOTE_ADDR']
);
$recaptcha_options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($recaptcha_data)
)
);
$recaptcha_context = stream_context_create($recaptcha_options);
$recaptcha_result = @file_get_contents($recaptcha_url, false, $recaptcha_context);
if ($recaptcha_result === false) {
// Log reCAPTCHA API failure but don't block submission
error_log("reCAPTCHA API call failed for IP: " . $_SERVER['REMOTE_ADDR']);
} else {
$recaptcha_json = json_decode($recaptcha_result, true);
if (!$recaptcha_json['success'] || $recaptcha_json['score'] < RECAPTCHA_THRESHOLD) {
// Log suspicious activity and block
$logEntry = date('Y-m-d H:i:s') . " - RECAPTCHA FAILED: Score " . ($recaptcha_json['score'] ?? '0') . " from " . $_SERVER['REMOTE_ADDR'] . "\n";
file_put_contents('logs/contact-errors.log', $logEntry, FILE_APPEND | LOCK_EX);
// Add to blocked IPs if score is very low
if (isset($recaptcha_json['score']) && $recaptcha_json['score'] < 0.3) {
$blockEntry = $_SERVER['REMOTE_ADDR'] . '|' . time() . "\n";
file_put_contents('logs/blocked-ips.txt', $blockEntry, FILE_APPEND | LOCK_EX);
}
sendResponse(false, 'Security verification failed. Please try again.');
}
}
} else {
// No reCAPTCHA response - likely a bot
sendResponse(false, 'Security verification required.');
}
// Validate and sanitize inputs
$name = validateInput($_POST['name'] ?? '', 'text');
$email = validateInput($_POST['email'] ?? '', 'email');
@@ -182,9 +233,24 @@ $spamKeywords = [
'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'
'sex', 'dating', 'singles', 'webcam', 'escort', 'massage', 'crypto', 'nft',
'blockchain', 'earn money', 'passive income', 'financial freedom', 'mlm',
'network marketing', 'online casino', 'gambling', 'betting', 'binary options'
];
// Check for disposable email domains
$disposableEmailDomains = [
'mailinator.com', 'guerrillamail.com', '10minutemail.com', 'temp-mail.org',
'throwawaymail.com', 'yopmail.com', 'mailnesia.com', 'trashmail.com',
'maildrop.cc', 'mailcatch.com', 'tempmail.com', 'email-fake.com',
'fakeinbox.com', 'sharklasers.com', 'guerrillamailblock.com'
];
$emailDomain = substr(strrchr($email, "@"), 1);
if (in_array(strtolower($emailDomain), $disposableEmailDomains)) {
sendResponse(false, 'Please use a valid business email address.');
}
$messageContent = strtolower($message . ' ' . $name . ' ' . $company);
foreach ($spamKeywords as $keyword) {
if (strpos($messageContent, $keyword) !== false) {
@@ -209,6 +275,39 @@ if (isset($_SESSION['form_start_time'])) {
}
}
// Check for XMLHttpRequest header (JavaScript submission)
if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] !== 'XMLHttpRequest') {
// Log direct POST attempt
$logEntry = date('Y-m-d H:i:s') . " - DIRECT POST attempt from " . $_SERVER['REMOTE_ADDR'] . "\n";
file_put_contents('logs/contact-errors.log', $logEntry, FILE_APPEND | LOCK_EX);
sendResponse(false, 'Invalid submission method');
}
// Verify interaction token (human behavior verification)
if (isset($_POST['interaction_token']) && !empty($_POST['interaction_token'])) {
$tokenData = @json_decode(base64_decode($_POST['interaction_token']), true);
if ($tokenData && isset($tokenData['score'])) {
if ($tokenData['score'] < 30) {
// Log low interaction score
$logEntry = date('Y-m-d H:i:s') . " - LOW INTERACTION SCORE: " . $tokenData['score'] . " from " . $_SERVER['REMOTE_ADDR'] . "\n";
file_put_contents('logs/contact-errors.log', $logEntry, FILE_APPEND | LOCK_EX);
sendResponse(false, 'Please complete the form normally');
}
}
}
// Verify form timestamp (prevent replay attacks)
if (isset($_POST['form_timestamp'])) {
$formTimestamp = intval($_POST['form_timestamp']);
$currentTime = time() * 1000; // Convert to milliseconds
$timeDiff = $currentTime - $formTimestamp;
// Form older than 1 hour or from the future
if ($timeDiff > 3600000 || $timeDiff < 0) {
sendResponse(false, 'Form session expired. Please refresh and try again.');
}
}
// Update rate limit counter
$ip = $_SERVER['REMOTE_ADDR'];
$key = 'contact_' . md5($ip);