Fixes.
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user