From ccc9a05b758f1dc0313b96807edfc447a9e8d278 Mon Sep 17 00:00:00 2001 From: polo Date: Thu, 8 Feb 2024 04:31:14 +0100 Subject: RGPD cookie uniquement en mode admin et avertissement, logo journal --- controller/ajax.php | 15 +- controller/backup.php | 8 +- controller/ckeditor.php | 7 +- controller/config.php | 4 +- controller/cookies.php | 66 +++++++++ controller/installation.php | 15 +- controller/password.php | 346 ++++++++++++++++++++++++-------------------- 7 files changed, 285 insertions(+), 176 deletions(-) create mode 100644 controller/cookies.php (limited to 'controller') diff --git a/controller/ajax.php b/controller/ajax.php index 1a4909e..96df9cb 100644 --- a/controller/ajax.php +++ b/controller/ajax.php @@ -4,12 +4,12 @@ // traitement des requêtes AJAX -// -> insertion d'une image dans l'éditeur +// éditeur +// -> insertion d'une image if(isset($_GET['action']) && isset($_GET['page']) && $_GET['action'] == 'upload_image') { // sécurité !! - if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1 - || !isset($_FILES['upload']) || empty($_FILES['upload'])) + if(!isset($_SESSION) || !isset($_FILES['upload']) || empty($_FILES['upload'])) { // sans effet? header('Location: index.php?erreur=image_ajax'); @@ -48,7 +48,7 @@ if(isset($_GET['action']) && isset($_GET['page']) && $_GET['action'] == 'upload_ if(isset($_GET['action']) && $_GET['action'] == 'restauration' && isset($_GET['file_name']) && isset($_GET['file_size'])) { - if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1) + if(!isset($_SESSION)) { header('Location: index.php?erreur=file_infos_ajax'); } @@ -56,8 +56,6 @@ if(isset($_GET['action']) && $_GET['action'] == 'restauration' { $_SESSION['fileSize'] = $_GET['file_size']; $_SESSION['fileName'] = $_GET['file_name']; - //echo("file infos send"); - //var_dump($_SESSION['fileName']); exit(); // stop !! } } @@ -65,8 +63,7 @@ if(isset($_GET['action']) && $_GET['action'] == 'restauration' if(isset($_GET['action']) && $_GET['action'] == 'restauration' && isset($_GET['chunk_name']) && isset($_FILES['blob'])) { - - if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1) + if(!isset($_SESSION)) { header('Location: index.php?erreur=upload_ajax'); } @@ -79,7 +76,7 @@ if(isset($_GET['action']) && $_GET['action'] == 'restauration' } } -// nettoyage +// nettoyage systématique if(!isset($_GET['action']) || $_GET['action'] != 'restauration') { if(isset($_SESSION['fileName'])) diff --git a/controller/backup.php b/controller/backup.php index c10ca21..52f300f 100644 --- a/controller/backup.php +++ b/controller/backup.php @@ -10,7 +10,7 @@ function pageSauvegarde($from) $date = date("d-m-Y", time()); $nomFichier = "melaineDATA_" . $date; // ne prendre que les dossiers pour exclure les fichiers password.txt, melaineDATA.zip et melainePHP.zip existant - $dossiersCibles = [ 'data/archives', 'data/musique', 'data/jaime', 'data/presse', 'data/livres', 'data/legal', 'data/discographie', 'data/melaine', 'data/peinture' ]; + $dossiersCibles = [ 'data/menu', 'data/archives', 'data/musique', 'data/jaime', 'data/presse', 'data/livres', 'data/legal', 'data/discographie', 'data/melaine', 'data/peinture' ]; //$fichiersALaRacine = []; createZip($cheminDestination, $nomFichier, $dossiersCibles); @@ -177,7 +177,7 @@ function pageRestauration($from) $message = restoreData($path); } - // variables obtenues en AJAX + // variables crées dans ajax.php if(isset($_SESSION['fileName'])) { unset($_SESSION['fileName']); @@ -206,8 +206,8 @@ function pageRestauration($from) require('view/backup.php'); } -// upload AJAX d'un zip dans file_upload.js -function uploadChunkAndMerge() +// upload AJAX d'un zip en morceaux dans file_upload.js +function uploadChunkAndMerge() // appel dans ajax.php { // $_GET['chunk_name'] n'est pas utilisé pour l'instant diff --git a/controller/ckeditor.php b/controller/ckeditor.php index 1707128..d0c5824 100644 --- a/controller/ckeditor.php +++ b/controller/ckeditor.php @@ -18,8 +18,9 @@ function preparationCKeditor($html) header('Location: index.php?erreur=empty_input'); } - // supprimer espaces, tabulations et sauts de ligne en début et fin de chaine - $html = trim($html); + // sécuriser le HTML + require('controller/Security.php'); + $html = Security::secureString($html); // supprimer les sauts de ligne $sautsDeLigne = array("\n", "\r", "\r\n"); @@ -58,7 +59,7 @@ function getFileCodeFromHTTPReferrer(): string function submitCKeditor() { // déjà fait mais on ne sait jamais - if(!isset($_SESSION['admin']) || $_SESSION['admin'] != 1) + if(!isset($_SESSION)) { header('Location: index.php?page=' . $_GET['page'] . '&erreur=connexion'); exit(); diff --git a/controller/config.php b/controller/config.php index 6fc7000..804671b 100644 --- a/controller/config.php +++ b/controller/config.php @@ -34,7 +34,7 @@ else echo(''); } -// format dans lequel créer les sauvegardes +// format dans lequel créer les sauvegardes, // zip uniquement pour l'instant if(extension_loaded("zip")) { @@ -48,7 +48,7 @@ else // conversion des 2M du php.ini en 2000000 // note: les kibi, mébi et gibi sont inutiles ici -function returnBytes ($size_str) // chaine du style '2M' +function returnBytes($size_str) // chaine du style '2M' { switch (substr ($size_str, -1)) { diff --git a/controller/cookies.php b/controller/cookies.php new file mode 100644 index 0000000..f5c7e64 --- /dev/null +++ b/controller/cookies.php @@ -0,0 +1,66 @@ + 0, + 'path' => '/', + 'domain' => $_SERVER['HTTP_HOST'], + 'secure' => true, + 'httponly' => true, + 'samesite' => 'strict']); + session_start();*/ + + /*session_start([ + 'cookie_lifetime' => 0, + 'cookie_path' => '/', + 'cookie_domain' => $_SERVER['HTTP_HOST'], + 'cookie_secure' => true, + 'cookie_httponly' => true, + 'cookie_samesite' => 'strict']);*/ + session_start(); + + // le cookie ne semble pas prendre les paramètres! pourquoi? + //var_dump(session_get_cookie_params()); + } + else // cas anormal: session déjà démarrée, mode parano activé! + { + deleteCookie($cookie); + header("Location: index.php"); + exit(); + } +} + +// erreurs affichées au rechargement (lesquelles déjà?) +if(isset($_SESSION['erreur']) && !empty($_SESSION['erreur'])) +{ + echo(''); + unset($_SESSION['erreur']); +} + + +function deleteCookie(string $name) +{ + unset($_COOKIE[$name]); // utile? + setcookie($name, '', time() - 4200, '/'); // suppression + + // cookie supprimé au prochain chargement de la page + // forcer un rechargement pour effet immédiat + //header("Location: index.php"); + //exit(); +} diff --git a/controller/installation.php b/controller/installation.php index f0d2890..90dcd28 100644 --- a/controller/installation.php +++ b/controller/installation.php @@ -1,5 +1,7 @@ caractères HTML dangereux supprimés + // -> empêche validation par erreur d'une chaine "vide" + require('controller/Security.php'); + $password = Security::secureString($_POST['motdepasse']); + $password = removeSpacesTabsCRLF($_POST['motdepasse']); + + // enregistrement et redirection + if(isset($password) && $password == $_POST['motdepasse']) + { + hashNewPassword($_POST['motdepasse']); + header('Location: index.php'); + exit(); + } + else + { + $error = 'bad_password'; + } } } - // saisie non valide - elseif(isset($_POST['captcha']) && controlCaptchaInput() == 0) - { - sleep(1); - echo($header); - echo($errorNonValidCaptcha); - echo($formulaireNouveauMDP); - echo($errorBadCharacters); - } - // mauvais captcha - elseif(isset($_POST['captcha']) && (int) $_POST['captcha'] != $_SESSION['captcha']) + else // première fois + {} + + // inséré dans $captchaHtml puis dans $formulaireNouveauMDP + $captcha = createCaptcha(); + // enregistrement de la réponse du captcha pour vérification + saveSolutionCaptcha($captcha[2]); + + + // II - affichage + $title = 'Bienvenue Melaine Favennec'; + $subHeading = 'Veuillez choisir le mot de passe que vous utiliserez pour gérer le site.'; + + // même vue que la fonction changerMotDePasse() + require('view/password.php'); + + echo($header); + if($error != '') { sleep(1); - echo($header); - echo($errorCaptcha); - echo($formulaireNouveauMDP); - echo($errorBadCharacters); - } - // 1ère fois - else - { - echo($header); - echo($formulaireNouveauMDP); - echo($errorBadCharacters); - //echo($warning); // message pas top + echo($error_messages[$error]); } + echo($formulaireNouveauMDP); + echo($error_messages['forbidden_characters']); echo($footer); - - // fois suivante (dispense de nettoyer la variable) - $_SESSION['captcha'] = $captcha[2]; - exit(); } function connect() { + // I - traitement // déjà en mode admin - if($_SESSION['admin'] == 1) + global $cookie; // nom du cookie dans cookies.php + if(isset($_COOKIE[$cookie])) { - header('Location: index.php?page=' . $_GET['from']); - exit(); + header('Location: index.php?page=' . $_GET['from']); + exit(); } - // Ajouter une sécurité par cpatcha avec un "input" supplémentaire + // contrôle de la saisie + $file_name = 'data/tmp/solution.txt'; + $error = ''; + if(file_exists($file_name)) + { + $captcha_solution = file_get_contents($file_name); + unlink($file_name); + + if(empty($_POST)) // page rechargée + {} + elseif(!isset($_POST['captcha']) || controlCaptchaInput() == 0) + { + $error = 'error_non_valid_captcha'; + } + elseif($_POST['captcha'] != $captcha_solution) + { + $error = 'bad_solution_captcha'; + } + elseif(!isset($_POST['motdepasse']) || empty($_POST['motdepasse'])) + { + $error = 'bad_password'; + } + else + { + // enregistrement et redirection + if(testPassword($_POST["motdepasse"])) + { + session_name($cookie); + session_start(); + header('Location: index.php?page=' . $_GET['from']); + exit(); + } + else + { + $error = 'bad_password'; + } + } + } + else // première fois + {} + + // inséré dans $captchaHtml puis dans $formulaireNouveauMDP $captcha = createCaptcha(); - // Et créer une variable de session pour la réponse au CAPTCHA + // enregistrement de la réponse du captcha pour vérification + saveSolutionCaptcha($captcha[2]); + + // II - affichage $title = "Connexion"; $subHeading = "Veuillez saisir votre mot de passe pour pouvoir apporter des modifications au site."; - - // cette page utilise la même vue que la fonction changerMotDePasse() dans controller/admin.php + // même vue que la fonction changerMotDePasse() require('view/password.php'); echo($header); - - // bon codes (mot de passe et captcha) - if(isset ($_POST["motdepasse"]) && testPassword($_POST["motdepasse"]) && isset($_POST['captcha']) && (int) $_POST['captcha'] == $_SESSION['captcha']) - { - $_SESSION['admin'] = 1; - unset($_SESSION['captcha']); // nettoyage - header('Location: index.php?page=' . $_GET['from']); - exit(); - } - // saisie non valide - elseif(isset($_POST['captcha']) && controlCaptchaInput() == 0) - { - echo($errorNonValidCaptcha); - sleep(1); - echo($formulaireConnexion); - } - // mauvais captcha - elseif(isset($_POST['captcha']) && (int) $_POST['captcha'] != $_SESSION['captcha']) + //echo($warning_messages['message_disconnect']); + if($error != '') { - echo($errorCaptcha); sleep(1); - echo($formulaireConnexion); + echo($error_messages[$error]); } + echo($formulaireConnexion); + echo($warning_messages['message_cookie']); + echo($warning_messages['private_browsing']); + echo($footer); +} - // mauvais codes - elseif(isset ($_POST["motdepasse"]) && !testPassword($_POST["motdepasse"])) - { - // défense aux attaques par force brute - // pas parfait, ne marche pas si l'attaquant multiplie les connexions au site - echo($errorPassword); - sleep(1); - echo($formulaireConnexion); - } - // première arrivée sur la page - else - { - echo($formulaireConnexion); - } - - // fois suivante (dispense de nettoyer la variable) - $_SESSION['captcha'] = $captcha[2]; - - echo($messageDeconnect); - echo($footer); +function saveSolutionCaptcha(string $solution) +{ + $file_name = 'data/tmp/solution.txt'; + if(!file_exists($file_name)) + { + touch($file_name); + chmod($file_name, 0600); + } + file_put_contents($file_name, $solution); } + function changePassword() { + // I - traitement // vérification supplémentaire - if($_SESSION['admin'] !== 1) + global $cookie; // nom du cookie dans cookies.php + if(!isset($_SESSION)) { - $_SESSION['admin'] = 0; + deleteCookie($cookie); header('Location: index.php?page=' . $_GET['from']); exit(); } - $title = "Nouveau mot de passe"; - $subHeading = "Veuillez saisir votre actuel mot de passe suivi du nouveau."; - - require('view/password.php'); - echo($header); - - // conformité du nouveau mot de passe - if(isset($_POST['nouveauMotdepasse']) && !empty($_POST['nouveauMotdepasse'])) + // contrôle de la saisie + $error = ''; + $success = false; + if(empty($_POST)) // première fois ou page rechargée + {} + elseif(!isset($_POST['nouveauMotdepasse']) || empty($_POST['nouveauMotdepasse'])|| !isset($_POST['ancienMotdepasse']) || empty($_POST['ancienMotdepasse'])) + { + $error = 'bad_password'; + } + else { require('controller/Security.php'); $newPassword = Security::secureString($_POST['nouveauMotdepasse']); $newPassword = removeSpacesTabsCRLF($_POST['nouveauMotdepasse']); - } - // bon mot de passe - if(isset($newPassword) && $newPassword === $_POST['nouveauMotdepasse'] - && isset ($_POST["ancienMotdepasse"]) && testPassword($_POST["ancienMotdepasse"])) - { - // enregistrement et confirmation - hashNewPassword($_POST["nouveauMotdepasse"]); - echo($message); + if(isset($newPassword) && $newPassword !== $_POST['nouveauMotdepasse']) // erreur de conformité + { + $error = 'forbidden_characters'; + } + else + { + if(testPassword($_POST["ancienMotdepasse"])) + { + // enregistrement et confirmation + hashNewPassword($_POST["nouveauMotdepasse"]); + $success = true; + } + else + { + $error = 'bad_password'; + } + } } - // mauvais mot de passe - elseif(isset ($_POST["ancienMotdepasse"]) && !testPassword($_POST["ancienMotdepasse"])) + + + // II - affichage + $title = "Nouveau mot de passe"; + $subHeading = "Veuillez saisir votre actuel mot de passe suivi du nouveau."; + + require('view/password.php'); + + echo($header); + if($error != '') { - // défense aux attaques par force brute - // pas parfait, ne marche pas si l'attaquant multiplie les connexions au site - echo($errorPassword); sleep(1); - echo($formulaireModifMDP); + echo($error_messages[$error]); } - // erreur de conformité - elseif(isset($newPassword) && $newPassword !== $_POST['nouveauMotdepasse']) + elseif($success) { - echo($errorBadCharacters); - echo($formulaireModifMDP); + echo($alertJSNewPassword); } - // première arrivée sur la page - else - { - echo($formulaireModifMDP); - } - - //echo($warning); + echo($formulaireModifMDP); echo($footer); } -// hachage function hashNewPassword(string $newPassword) { - // "réparation" des espaces accidentels - $newPassword= trim($newPassword); // hachage $newHashedPassword = password_hash($newPassword, PASSWORD_DEFAULT); @@ -306,14 +347,9 @@ function hashNewPassword(string $newPassword) function testPassword(string $password): bool { - // lecture - $oldHashedPassword = file_get_contents('data/password.txt'); - - // "réparation" des espaces accidentels - $password= trim($password); - $oldHashedPassword = trim($oldHashedPassword); + $hashedPassword = file_get_contents('data/password.txt'); - if(password_verify($password, $oldHashedPassword)) + if(password_verify($password, $hashedPassword)) { return true; } -- cgit v1.2.3