[Php] Sécurisation formulaire envoi de mail - kaizo - 03-10-2012
Salut a tous !
J'ai sur mon site un formulaire d'envoi par mail en php avec captcha, et je voudrais savoir simplement si il est suffisamment sécurisé, alors je vous donne le code, merci à ceux qui prendront le temps de le regarder
d'abord le formulaire:
Code : <form id="contact" method="post" action="mail.php">
<fieldset><legend>coordonnées</legend>
<p><label for="nom">Nom :</label><input type="text" id="nom" name="nom" tabindex="1" maxlength="20" size="20"/></p>
<p><label for="prenom">Prénom :</label><input type="text" id="prenom" name="prenom" tabindex="1" maxlength="20" size="20" /></p>
<p><label for="email">Email :</label><input type="text" id="email" name="email" tabindex="2" /></p>
</fieldset>
<fieldset><legend>message :</legend>
<p><label for="objet">Objet :</label><input type="text" id="objet" name="objet" tabindex="3" /></p>
<p><label for="message">Message :<br/></label><textarea id="message" name="message" tabindex="4" cols="50" rows="10"></textarea></p>
<label for="code"> somme des deux nombres dans la case </label>
<img title="cap" src="captcha.php" alt="Cap" />
<input id="captcha" name="captcha" type="text" maxlength="2" size="3"/>
</fieldset>
<div style="text-align:center;"><input class="bouton" type="submit" name="envoi" value="Envoyer" /></div>
</form>
ensuite le script d'envoi mail.php (récupérer sur un site a l'origine, je sais plus où, et modifier ensuite) :
Code PHP : $destinataire = 'blabla@blabla.fr';
// copie ? (envoie une copie au visiteur) $copie = 'oui';
// Messages de confirmation du mail $message_envoye = "Votre message a été envoyé !"; $message_non_envoye = "L'envoi du mail a échoué, veuillez réessayer SVP.<br/><a href=contact.php >Cliquez ici pour réessayer</a>";
// Messages d'erreur du formulaire $message_erreur_formulaire = "Vous devez d'abord <a href=\"contact.php\">envoyer le formulaire</a>."; $message_formulaire_invalide = "Vérifiez ."; $message_captcha = "Résultat faux ! <br/> "; /* ******************************************************************************************** FIN DE LA CONFIGURATION ******************************************************************************************** */
// on teste si le formulaire a été soumis if (!isset($_POST['envoi'])) { // formulaire non envoyé echo '<p>'.$message_erreur_formulaire.'</p>'."\n"; } //captcha else if(isset($_POST['captcha'])) // Si on a validé le formulaire. if($_SESSION['resultat_captcha'] != $_POST['captcha']) { // Si le résultat est faux. echo '<p class="mil">'.$message_captcha.'<br/> <a href="javascript:history.go(-1);">Retour au formulaire</a> </p>'."\n"; } else { /* * cette fonction sert à nettoyer et enregistrer un texte */ function Rec($text) { $text = trim($text); // delete white spaces after & before text if (1 === get_magic_quotes_gpc()) { $stripslashes = create_function('$txt', 'return stripslashes($txt);'); } else { $stripslashes = create_function('$txt', 'return $txt;'); }
// magic quotes ? anti xss $text = $stripslashes($text); $text = htmlspecialchars($text, ENT_QUOTES); $text = nl2br($text); return $text; };
/* * vérification syntaxe email */ function IsEmail($email) { $pattern = "#^([a-z0-9_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,7}$#"; return (preg_match($pattern,$email)) ? true : false; };
// formulaire envoyé, on récupère tous les champs. $nom = (isset($_POST['nom'])) ? Rec($_POST['nom']) : ''; $prenom = (isset($_POST['prenom'])) ? Rec($_POST['prenom']) : ''; $email = (isset($_POST['email'])) ? Rec($_POST['email']) : ''; $objet = (isset($_POST['objet'])) ? Rec($_POST['objet']) : ''; $message = (isset($_POST['message'])) ? Rec($_POST['message']) : '';
// On va vérifier les variables et l'email ... $email = (IsEmail($email)) ? $email : '';
if (($nom != '') && ($email != '') && ($objet != '') && ($message != '')) { // les 4 variables sont remplies, on génère puis envoie le mail $headers = 'From: '.$nom.' <'.$email.'>' . "\r\n";
// envoyer une copie au visiteur ? if ($copie == 'oui') { $cible = $destinataire.','.$email; } else { $cible = $destinataire; };
// Remplacement de certains caractères spéciaux $message = str_replace("'","'",$message); $message = str_replace("’","'",$message); $message = str_replace(""",'"',$message); $message = str_replace('<br>','',$message); $message = str_replace('<br />','',$message); $message = str_replace("<","<",$message); $message = str_replace(">",">",$message); $message = str_replace("&","&",$message);
// Envoi du mail if (mail($cible, $objet, $message, $headers)) { echo '<p class="mil">'.$message_envoye.'<br/><a href=index.php>Cliquez ici pour revenir à l\'accueil</a></p>'."\n"; } else { echo '<p class="mil">'.$message_non_envoye.'</p>'."\n"; }; } else { // une des 3 variables (ou plus) est vide ... echo '<p class="mil">'.$message_formulaire_invalide.' <br/><a href="javascript:history.go(-1);">Retour au formulaire</a></p>'."\n"; }; }; // fin du if (!isset($_POST['envoi']))
?>
et enfin le captcha :
Code PHP : <?php session_start(); // On ouvre une session, car on va en utiliser plus loin. header ("Content-type: image/png"); // On indique le format de l'image. $image = imagecreate(80,20); // On indique les dimensions de l'image. $fond = imagecolorallocate($image, 255, 255, 255); // On renseigne ici la couleur de fond. $couleur_texte = imagecolorallocate($image, 44, 143, 228); // On indique la couleur du texte.
$nbre1 = rand(1,10); $nbre2 = rand(1,10); // On crée nos deux nombres avec chacun un chiffre aléatoire associé.
$_SESSION['resultat_captcha'] = $nbre1 + $nbre2; // Le résultat numérique de l'addition. $_SESSION['addition'] = $nbre1.' + '. $nbre2; // L'addition sous forme textuelle.
imagestring($image, 6, 2, 2, $_SESSION['addition'], $couleur_texte); // Enfin on insère le texte avec la couleur précisée dans l'image.
imagepng($image); // On génère l'image. imagedestroy($image); // On libère la mémoire associée à l'image. ?>
Voilà, merci encore aux bonnes âmes
RE: [PHP] Sécurisation formulaire envoi de mail - InstinctHack - 03-10-2012
Je regarde ca demain (je suis sur phone la... :/ )
RE: [PHP] Sécurisation formulaire envoi de mail - kaizo - 03-10-2012
pas de soucis, ya aucune urgence ^^
RE: [PHP] Sécurisation formulaire envoi de mail - supersnail - 03-10-2012
Bonjour,
IMHO y'a une petite "vulnérabilité" qui fait que ton captcha a une chance non nulle de ne servir à rien. En effet, un utilisateur peut forger une requête HTTP en envoyant un cookie PHPSESSID bidon, ce qui fera voir à PHP une nouvelle session... où la variable de session "resultat_captcha" n'a pas été définie (donc considérée comme "nulle" par PHP). Ainsi en foutant rien dans ton $_POST["captcha"], tu bypass sans problème le captcha.
Pour remédier à ce problème, faut juste faire un isset($_SESSION["resultat_captcha"]) et inviter l'utilisateur à GTFO si cette variable de session n'existe pas
RE: [PHP] Sécurisation formulaire envoi de mail - Swissky - 03-10-2012
C'est pas vraiment une faille mais ton captcha se bruteforce assez simplement , les 2 valeurs pour l'addition étant très simple , chacune de 1 à 10 , les résultats possible sont donc de 0 à 20 .
tu compliquerais les choses avec des virgules ou alors des nombres sensiblement (0,1000) plus grand ou bien avec des captcha existant comme ceux de Google ^^
A la limite :
"Justin Richer 28-Mar-2012 06:43
Since many people (myself included) come to this page looking for a way to do a random string, I present a way that uses arrays and shuffle() instead of rand(). This also has the effect of not repeating any characters in the value set."
Code PHP : $arr = str_split('ABCDEFGHIJKLMNOP'); // get all the characters into an array shuffle($arr); // randomize the array $arr = array_slice($arr, 0, 6); // get the first six (random) characters out $str = implode('', $arr); // smush them back into a string
Et tu demandes juste d'entrer la valeur affichée au lieu de faire une addition ^^
RE: [PHP] Sécurisation formulaire envoi de mail - kaizo - 04-10-2012
Merci d’avoir répondu
(03-10-2012, 19h27)supersnail a écrit : Bonjour,
IMHO y'a une petite "vulnérabilité" qui fait que ton captcha a une chance non nulle de ne servir à rien. En effet, un utilisateur peut forger une requête HTTP en envoyant un cookie PHPSESSID bidon, ce qui fera voir à PHP une nouvelle session... où la variable de session "resultat_captcha" n'a pas été définie (donc considérée comme "nulle" par PHP). Ainsi en foutant rien dans ton $_POST["captcha"], tu bypass sans problème le captcha.
Pour remédier à ce problème, faut juste faire un isset($_SESSION["resultat_captcha"]) et inviter l'utilisateur à GTFO si cette variable de session n'existe pas
pourtant si on ne met rien dans le captcha, il indique "résultat faux" grace a Code PHP : else if(isset($_POST['captcha']))
, alors comment peut on le bypasser en ne mettant rien ?
@swissky :
merci pour le code, je vais l'updater, mon captcha a trois ans et était censé être temporaire, mais parfois ya du provisoire qui dure ^^
RE: [PHP] Sécurisation formulaire envoi de mail - supersnail - 04-10-2012
Ben le truc c'est que si tu envoies "&captcha=" au serveur, bah ta variable est bien définie, mais elle est nulle.
isset détecte juste le fait que ta variable existe aux yeux de php ou non, pas si elle est nulle (c'est la fonction empty qui sert à ça )
RE: [PHP] Sécurisation formulaire envoi de mail - CyberSee - 04-10-2012
Ça me fait penser, j'avais partager un post sur les captchas ici
http://n-pn.fr/forum/showthread.php?tid=1263
Code PHP : if( $_SESSION['security_code'] == $_POST['security_code'] && !empty($_SESSION['security_code'] ) ) { // Le code est bon } else { echo "- Désolé, vous devez copier le contenu de l'image dans le champ sécurité.<br>$err"; }
RE: [PHP] Sécurisation formulaire envoi de mail - kaizo - 05-10-2012
bon j'ai modifié mon code comme ceci :
Code PHP : if($_SESSION['resultat_captcha'] != $_POST['captcha'] && empty($_SESSION['resultat_captcha'] )) { // Si le résultat est faux. echo '<p class="mil">'.$message_captcha.'<br/> <a href="javascript:history.go(-1);">Retour au formulaire</a> </p>'."\n"; }
j'ai donc rajouter && empty($_SESSION['resultat_captcha'] )
cela doit combler la brèche, non ?
en tout cas merci encore.
ps : ça pourrait presque faire partie d'un challenge de bypass de captcha
RE: [PHP] Sécurisation formulaire envoi de mail - supersnail - 05-10-2012
Bonjour
Code PHP : if($_SESSION['resultat_captcha'] != $_POST['captcha'] || empty($_SESSION['resultat_captcha'] ))
serait mieux (sinon si le captcha est faux et que ta session n'est pas vide, le empty renvoie false et du coup la condition est fausse).
RE: [PHP] Sécurisation formulaire envoi de mail - kaizo - 05-10-2012
ah oui, pas faux ! merci pour la correction ^^
|