0, 'path' => '/', 'domain' => '', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict' ]); if (session_status() === PHP_SESSION_NONE) { session_start(); } /* -- HEADERS DE SΓCURITΓ -- */ header('X-Frame-Options: SAMEORIGIN'); header('X-Content-Type-Options: nosniff'); header('Referrer-Policy: no-referrer'); header('Permissions-Policy: geolocation=(), microphone=(), camera=()'); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Pragma: no-cache"); header("Expires: 0"); /* -- CONFIGURATION CONSTANTES SCSE -- */ define('SCSE_VERSION', '2.5.2'); define('nam_site', "Feuille d'heures AngΓ©lique πΌ"); //////// * a remplire / Modifier ** define('SCSE_NOM', "Feuille d'heures AngΓ©lique"); //////// * a remplire / Modifier ** define('SCSE_AUTEUR', 'sync'); define('SCSE_SITE_URL', 'URL de votre site'); //////// * a remplire / Modifier ** define('SCSE_EMAIL_DESTINATAIRE', 'Votre E-mail@mail.com'); //////// * a remplire / Modifier ** define('SCSE_EMAIL_EXPEDITEUR', 'contact@ (ICI) .net'); //////// * a remplire / Modifier ** l'adress sans (https// | https//www.) define('DOSSIER_DATA', __DIR__ . "/data_contact/"); define('DOSSIER_LOGS', DOSSIER_DATA . "logs/"); define('DOSSIER_TMP', DOSSIER_DATA . "tmp/"); /* -- CRΓATION DES DOSSIERS -- */ foreach ([DOSSIER_DATA, DOSSIER_LOGS, DOSSIER_TMP] as $dossier) { if (!is_dir($dossier)) { mkdir($dossier, 0755, true); } } /* -- CRΓATION DES FICHIERS LOGS -- */ foreach (["surveillance.txt", "envois.txt", "bloques.txt", "erreurs.txt"] as $fichier) { $chemin = DOSSIER_LOGS . $fichier; if (!file_exists($chemin)) { file_put_contents($chemin, ""); } } /* -- INITIALISATION DES VARIABLES -- */ $messageRetour = ""; $emailExpediteur = ""; $sujet = ""; $message = ""; if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } function genererCaptcha(int $longueur = 6): string { $alphabet = "abcdefghijklmnpqrstuvwxyz123456789-/()@_&+*"; $captcha = ""; for ($i = 0; $i < $longueur; $i++) { $captcha .= $alphabet[random_int(0, strlen($alphabet) - 1)]; } $_SESSION['scse_captcha'] = $captcha; return $captcha; } // GΓ©nΓ¨re un nouveau CAPTCHA Γ chaque affichage de la page (si pas de soumission POST en cours) if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_SESSION['scse_captcha'])) { genererCaptcha(); } /* -- FONCTIONS UTILITAIRES ET SΓCURITΓ -- */ function journaliser(string $type, string $contenu): void { $fichiers = [ 'BLOCAGE' => DOSSIER_LOGS . "bloques.txt", 'ERREURS' => DOSSIER_LOGS . "erreurs.txt", 'SURVEILLANCE' => DOSSIER_LOGS . "surveillance.txt" ]; $fichier = $fichiers[$type] ?? DOSSIER_LOGS . "surveillance.txt"; file_put_contents($fichier, $contenu, FILE_APPEND | LOCK_EX); } function verifierBlocage(string $ip): bool { $fichierBlocage = DOSSIER_LOGS . "bloques.txt"; if (!file_exists($fichierBlocage)) return false; $lignes = file($fichierBlocage, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $maintenant = time(); foreach ($lignes as $ligne) { $infos = explode("|", $ligne); if (count($infos) >= 3) { $ipBloquee = trim($infos[0]); $dateFin = strtotime(trim($infos[2])); if ($ipBloquee === $ip && $dateFin !== false && $dateFin > $maintenant) { return true; } } } return false; } function nettoyerEmail(string $email): string|false { $email = trim(preg_replace('/\s+/', '', $email)); if (preg_match('/[\r\n]/', $email) || strlen($email) < 6 || strlen($email) > 254) { return false; } return filter_var($email, FILTER_VALIDATE_EMAIL) ? strtolower($email) : false; } function nettoyerMessage(string $msg): string|false { $msg = trim($msg); $msg = str_replace(["\r\n", "\r"], "\n", $msg); $msg = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $msg); $msg = strip_tags($msg); $msg = preg_replace('/<\?(php|=)?/i', '', $msg); $msg = str_replace('?>', '', $msg); $msg = preg_replace('/[ \t]+/', ' ', $msg); $msg = preg_replace("/\n{3,}/", "\n\n", $msg); $msg = trim($msg); $len = mb_strlen($msg, "UTF-8"); if ($len < 10 || $len > 280) { return false; } return $msg; } /* =================================================== TRAITEMENT DU FORMULAIRE (REQUΓTE POST UNIQUEMENT) ET ΓVITE LES ABUS DES VISITEURS =================================================== */ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $adresseIP = $_SERVER['REMOTE_ADDR'] ?? 'INCONNUE'; // 1. ContrΓ΄le CSRF if (empty($_POST['csrf_token']) || empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { $messageRetour = "β AccΓ¨s refusΓ© (Session invalide)."; } // 2. Honeypot anti-robot elseif (!empty($_POST['website'])) { $messageRetour = "β Envoi refusΓ©."; } // 3. VΓ©rification des blocages IP, et Γ©vite les abus des visiteurs elseif (verifierBlocage($adresseIP)) { $messageRetour = "β Votre accΓ¨s est temporairement limitΓ©."; } else { // RΓ©cupΓ©ration des saisies $rawEmail = $_POST['email'] ?? ''; $rawSujet = $_POST['sujet'] ?? ''; $rawMessage = $_POST['message'] ?? ''; $rawCaptcha = $_POST['captcha'] ?? ''; $emailExpediteur = $rawEmail; $sujet = $rawSujet; $message = $rawMessage; $emailClean = nettoyerEmail($rawEmail); $messageClean = nettoyerMessage($rawMessage); $sujetClean = trim(strip_tags($rawSujet)); // ContrΓ΄le du CAPTCHA $captchaValide = !empty($_SESSION['scse_captcha']) && hash_equals($_SESSION['scse_captcha'], strtolower(trim($rawCaptcha))); if (!$emailClean) { $messageRetour = "β Adresse e-mail invalide."; } elseif (mb_strlen($sujetClean) < 5 || mb_strlen($sujetClean) > 50) { $messageRetour = "β Le sujet doit contenir entre 5 et 50 caractΓ¨res."; } elseif (!$messageClean) { $messageRetour = "β Le message doit contenir entre 10 et 280 caractΓ¨res."; } elseif (!$captchaValide) { $messageRetour = "β Code de sΓ©curitΓ© (CAPTCHA) incorrect."; } else { // Anti-injection d'en-tΓͺtes SMTP $interdits = ["content-type:", "mime-version:", "multipart/mixed", "bcc:", "cc:", "to:", "reply-to:"]; $injection = false; foreach ($interdits as $mot) { if (stripos($emailClean, $mot) !== false || stripos($sujetClean, $mot) !== false || stripos($messageClean, $mot) !== false) { $injection = true; break; } } if ($injection) { $messageRetour = "β Contenu ou entΓͺtes refusΓ©s."; } else { // GΓ©nΓ©ration rΓ©fΓ©rence $idJournal = "SCSE-" . date("Ymd-His") . "-" . strtoupper(bin2hex(random_bytes(4))); // Mail Administrateur $contenuAdmin = "Message reΓ§u depuis le formulaire de contact\n\n". "RΓ©fΓ©rence : ".$idJournal."\n". "Date : ".date("d/m/Y H:i:s")."\n". "ExpΓ©diteur : ".$emailClean."\n". "IP : ".$adresseIP."\n\n". "Sujet : ".$sujetClean."\n". "----------------------------------------\n". $messageClean."\n"; $headersAdmin = [ "From: " . SCSE_NOM . " <" . SCSE_EMAIL_EXPEDITEUR . ">", "Reply-To: " . $emailClean, "MIME-Version: 1.0", "Content-Type: text/plain; charset=UTF-8" ]; $mailAdmin = mail(SCSE_EMAIL_DESTINATAIRE, $sujetClean, $contenuAdmin, implode("\r\n", $headersAdmin)); // Mail Confirmation Visiteur $contenuVisiteur = "Bonjour,\n\nNous confirmons la bonne rΓ©ception de votre message.\n\n". "RΓ©fΓ©rence : ".$idJournal."\n". "Sujet : ".$sujetClean."\n\n". "Ceci est un envoi automatique, merci de ne pas y rΓ©pondre.\n\n". SCSE_NOM; $headersVisiteur = [ "From: " . SCSE_NOM . " <" . SCSE_EMAIL_EXPEDITEUR . ">", "MIME-Version: 1.0", "Content-Type: text/plain; charset=UTF-8" ]; $mailVisiteur = mail($emailClean, "Confirmation - " . SCSE_NOM, $contenuVisiteur, implode("\r\n", $headersVisiteur)); if ($mailAdmin) { $messageRetour = "β Votre message a bien Γ©tΓ© envoyΓ©."; $log = "============================== SUCCΓS ==============================\n". "\tID : $idJournal | Date : ".date("d/m/Y H:i:s")."\n". "\tExpΓ©diteur : $emailClean | IP : $adresseIP\n". "\t====================================================================\n\n"; journaliser("SURVEILLANCE", $log); // Redirection automatique aprΓ¨s 3 secondes header("Refresh: 3; url=../index.html"); // RΓ©initialisation des champs aprΓ¨s envoi rΓ©ussi $emailExpediteur = ""; $sujet = ""; $message = ""; } else { $messageRetour = "β Une erreur est survenue lors de l'envoi."; journaliser("ERREURS", "ΓCHEC ENVOI MAIL ID: $idJournal | IP: $adresseIP\n"); } // RΓ©gΓ©nΓ©ration des jetons post-traitement $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); genererCaptcha(); } } } } ?>
Formulaire sΓ©curisΓ© par le moteur SCSE = SCSE_VERSION ?>.
Protection CSRF β’ CAPTCHA β’ Anti-spam β’ Journalisation