8791 sujets

Développement web côté serveur, CMS

Bonjour,
Après avoir créé la structure de mon site, je m'attelle au formulaire de contact en php. La récupération des données du formulaire ne me pose pas de soucis a priori. Par contre, j'ai du mal à évaluer si mon formulaire est suffisamment sécurisé, sachant que je n'utilise aucune base de données. J'aimerais savoir :

1 - si les tests que j'ai mis en place sont pertinents (je ne suis pas toujours sûr de bien saisir le fonctionnement de ces fonctions dans l'optique de sécuriser le formulaire)

2 - si ces tests sont suffisants ou s'il y en a d'autres à utiliser.

Par avance, merci.

Voici les trois tests :

1 - Pour supprimer les antislash d'une chaîne puis pour remplacer les balises HTML par leur code afin qu'elles ne soient plus interprétées :

if (get_magic_quotes_gpc())
  {
  $nom=stripslashes(trim($_POST['nom']));
	$nom=htmlspecialchars($nom, ENT_QUOTES, 'UTF-8');
	etc...
  }
	else
  {
  $nom=stripslashes(trim($_POST['nom']));
	$nom=htmlspecialchars($nom, ENT_QUOTES, 'UTF-8');
	etc...
  }


2 - Pour m'assurer que le formulaire est bien envoyé de mon site :

if($_SERVER['HTTP_REFERER'] != 'http://monserveur.com/')
  {
  header('Location:  http://monserveur.com/accueil.html');
 
	}


3 - Pour tester la tentative d'insertion d'en-tête dans les différents champs :

preg_match(/[\n\r]/, $nom);
Hello !
Je suis loin d'être un expert en sécurité, mais déjà quelques remarques :

-Oublie les histoires de Magic Quotes et met ta version de php à jour, c'est devenu obsolète depuis php 5.3 et n'existe tout simplement plus dans php 5.4 (et ça fait trèèès longtemps qu'on recommande de les désactiver quelque soit la version).

-Ensuite le traitement à faire sur les données récupérées par un formulaire dépendent avant tout de ce pour quoi tu vas les exploiter. Par exemple si c'est pour les insérer dans une base de donnée il faudra se méfier des insertions SQL et utiliser soit mysql_real_escape_string soit des requêtes préparées.
Si les données seront amenées à être un jour affichées sur une page web, il faudra se méfier des injections xss, et donc utiliser la fonction htmlspecialchars comme tu l'as fait.

-Concernant la vérification du HTTP_REFERER pourquoi pas, mais quand je poste sur un site sans passer par les formulaires (via curl ou autre...) une des première choses que je fais c'est de changer le header HTTP_REFERER pour mettre l'adresse du formulaire en question, et je ne pense pas être le seul à faire ça ^^
Modifié par BlueScreenJunky (01 Sep 2012 - 02:21)
Merci pour ta réponse,

Concernant les magic quotes, je sais bien que c'est obsolète depuis php 5.3, mais l'hébergeur chez lequel je suis actuellement ne propose que php 4 !... Smiley decu

Au sujet de la modification manuelle du HTTP_REFERER, je ne connaissais pas l'utilisation de curl pour remplir un formulaire. Cela-veut-il dire que le test sur HTTP_REFERER est inutile et qu'il peut être contourné ?
Sebkra a écrit :
Au sujet de la modification manuelle du HTTP_REFERER, je ne connaissais pas l'utilisation de curl pour remplir un formulaire. Cela-veut-il dire que le test sur HTTP_REFERER est inutile et qu'il peut être contourné ?

Exactement, les headers (dont HTTP_REFERER) sont envoyés par le navigateur. Et comme toute info envoyée par le navigateur, elle est sujette à caution: Si le 'navigateur' c'est un de mes scripts, je peux très bien faire un truc de ce genre :
<?php
$url = "http://somewebsite.com/script.php";

$postfields = array (
    "nom" => "Junky",
    "message" => "J'utilise ton formulaire de contact comme un fourbe",
);

$ch = curl_init ($urltopost);

curl_setopt ($ch, CURLOPT_REFERER, "http://epidote.pagesperso-orange.fr/");
curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0");
curl_setopt ($ch, CURLOPT_POST, true);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $datatopost);

curl_exec ($ch);
?>


Et pour ton script ce sera comme si j'avais rempli le formulaire depuis ton site avec Firefox 16. Si tu veux absolument éviter ça (mais c'est pas forcément une fin en soi), ce qui rend la tâche plus pénible c'est un bon CAPTCHA et/ou un token généré avec du javascript incompréhensible planqué au fin fond de tes scripts.
Modifié par BlueScreenJunky (01 Sep 2012 - 08:55)
Ok... Vraiment pas simple de sécuriser un simple formulaire de contact juste pour éviter le spam ou son détournement...

Et en ce qui concerne le test de tentative d 'insertion d'en-tête, l'expression est-elle correcte (voire utile ! Smiley decu ) ?

preg_match(/[\n\r]/, $nom);


Je réfléchissais également à la mise en place d'un captcha, simple et accessible. Je vais donc creuser de ce côté.

En tout cas, encore merci.
Je ne comprends pas bien ce que tu cherches à repérer avec ton preg_match en fait. A priori tu cherches s'il y a un retour chariot dans le champ, mais quel rapport avec les en-têtes ? (c'est pas forcément inutile, mais ça dépasse mes compétences, quelqu'un d'autre saura sans doute t'aider mais je suis curieux de savoir à quoi ça sert).

Pour éviter le spam pas de solution miracle malheureusement. Je m'étais renseigné là dessus il y a quelques temps pour des commentaires sur un blog, et il est ressorti de mes lectures que le meilleur compromis était d'avoir un captcha très très simple (pour ne pas gêner les utilisateurs) qui permet déjà de stopper les bots les plus rudimentaires, et ensuite de passer par un service comme akismet qui analyse le contenu du message pour déterminer s'il s'agit d'un spam. L'api d'akismet est assez simple à utiliser : on lui envoie des infos (titre, message, adresse mail etc.) et il dit s'il s'agit d'un spam ou non. Le seul défaut c'est qu'il y a un certain nombre de faux positifs, donc il faut prévoir un système pour vérifier à la main régulièrement (d'ou l'intérêt du captcha pour n'avoir que 20 messages à vérifier et pas 400).
D'après ce que j'ai pu lire, ces deux caractères servent de séparateurs d'en-tête de courrier électronique. Leur insertion permet d'expédier le mail à d'autres destinataires que celui prévu dans le formulaire, notamment en utilisant Bcc pur masquer la "fourberie"... Leur présence n'est logique que dans le corps du message.

Par contre, j'ai un doute sur la syntaxe : guillemets doubles ou pas, des infos contradictoires à ce sujet...
J'ai déjà pu éclaircir le sujet grâce à cet échange : j'oublie HTTP_REFERER, je conserve htmlspecialchars et la recherche d'entête, couplés à d'autres techniques d'identification. Je poursuis désormais dans la doc php.