8791 sujets

Développement web côté serveur, CMS

Bonjour,

je ne sais pas si c'est une faille de sécurité et ce qu'on peut en faire, mais voilà ce qui arrive :

Mon site perso possède une page de contact avec... un formulaire de contact ! Quand on veut me contacter, on remplit le formulaire (mail expéditeur, sujet, message) et ça m'envoie le tout par mail.

Hors, je viens de m'apercevoir qu'on peut faire traiter un message par mon formulaire rien qu'en copiant la source de ma page, en la sauvegardant chez soi (sur EasyPHP par exemple), et en modifiant la ligne

<form method="post" action="/contact.php">

par
<form method="post" action="http://www.monsiteperso.com/contact.php">

Smiley sweatdrop

Du coup, je me demande si on ne peut pas détourner mon formulaire... Si c'est utile, comment me protéger de cela ?

Voici le code de mon formulaire (tout tient en un seul fichier). Je vous épargne les champs antispam.


<?php
$email_webmaster = "moi@monsiteperso.com";

// === début de traitement des données du formulaire =======================================================

if (isset($_POST["envoyer"])){

	
// le formulaire a été soumis
        $etat = "erreur";
// Valeur par défaut. Prendra la valeur "ok" s'il n'y a pas d'erreur


        if (isset($_POST["email_expediteur"])) {
                 $email_expediteur = trim(stripslashes(htmlentities(strip_tags($_POST["email_expediteur"]))));
        }
        if (isset($_POST["titre"])) {
                 $_POST["titre"] = trim(stripslashes(strip_tags($_POST["titre"])));
        }
        if (isset($_POST["message"])) {
                 $message = trim(stripslashes(strip_tags($_POST["message"])));
				 $message = str_ireplace("http://","Site web : ",$message);
				 //--- si je laisse  http://  dans le message, le mail ne m'arrive jamais.
        }
        // --- test de la validité des champs saisis ---
        if (empty($_POST["email_expediteur"])) {
// il manque l'email de l'expéditeur
                 $erreur="Saisissez votre adresse email.";
        }
        elseif (!eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\.[a-z]{2,4}$",$email_expediteur)){
// l'adresse e-mail n'est pas valide
                 $erreur="Votre adresse e-mail n'est pas valide.";
        }
        elseif (empty($_POST["message"])) {
// le message est vide
                 $erreur="Saisissez un message.";
        }
        else {
// --- tous les champs sont correctement remplis: on pourra envoyer le mail ---
                 $etat="ok";
        }
	
}
else {
// --- le formulaire n'a pas été soumis ---
           $etat="attente";
}
// === fin de traitement des données du formulaire =======================================================
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Contact</title>
</head>
<body>
<?php
if ($etat!="ok"){// le formulaire n'a pas été soumis, ou soumis avec une erreur
         if ($etat=="erreur"){
//le formulaire a été soumis avec une erreur
                         echo "<p id=\"form_err\"><strong>".$erreur."</strong></p>\n";
// afficher le message d'erreur
         }
?>
        <form method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
		
		
		<p><label for="email_expediteur">Votre adresse e-mail :</label><br />
        <input type="text" size="40" name="email_expediteur" id="email_expediteur" value="<?php
        if (!empty($_POST["email_expediteur"])) {
// l'adresse email de l'expéditeur a été saisie: la réafficher
                echo htmlspecialchars($_POST["email_expediteur"],ENT_QUOTES);
        }
        ?>" />
        </p>
		
        <p><label for="titre">Titre de votre message :</label><br />
        <input type="text" size="40" name="titre" id="titre" value="<?php
        if (!empty($_POST["titre"])) {
// le titre du message a été saisi: le réafficher
                echo htmlspecialchars($_POST["titre"],ENT_QUOTES);
        }
        ?>" />
        </p>

        <p><label for="message">Message :</label><br />
        <textarea name="message" id="message" cols="40" rows="7"><?php
        if (isset($_POST["message"])) {
// le message a été saisi: le réafficher
                echo htmlspecialchars($_POST["message"],ENT_QUOTES);
        }
        ?></textarea><br />
        </p>
		
        <p><input type="submit" name="envoyer" value="Envoyer" />
        </p>
        </form>
<?php
}
else {
// le formulaire a été soumis sans erreur, on envoie le mail
        $entete = "From: ".$email_expediteur." <".$email_expediteur.">\n";
		$entete .= "Reply-to : $email_webmaster <$email_webmaster>\n";
		$entete .= "X-Mailer [langue]HP\n";
        $entete .= "MIME-Version: 1.0\n";
		$entete .= "Content-type: text/plain; charset=iso-8859-1\n";
		
		$message = "$message\n";
		
        if (@mail($email_webmaster,$_POST["titre"],$message,$entete)){
// mail envoyé
                echo "Votre message a été envoyé.<br />\n";
                echo "<a href=\"".$_SERVER["PHP_SELF"]."\">Retour au formulaire.</a><br />\n";
				echo "<a href=\"index.php\">Retour à la page d'accueil.</a>\n";
        }
        else {
// erreur lors de l'envoi du mail
                echo "Un problème s'est produit lors de l'envoi du message.\n";
                echo "<a href=\"".$_SERVER["PHP_SELF"]."\">Réessayez...</a>\n";
        }
}
?>
</body>
</html>

C'est un formulaire de contact que j'ai trouvé... euh... quelque part. Je l'ai modifié à ma sauce. Pour ce post, j'ai viré la mise en forme.

Merci de votre aide ! Smiley cligne
Modifié par Gasp75 (23 Apr 2008 - 14:57)
Hello Gasp75 et bienvenue Smiley cligne ,

à priori ce que tu décris est valable pour la grande majorité des formulaires de contact... et ça n'est pas bien grave Smiley langue ! Au pire tu recevras un mail comme s'il avait été envoyé depuis ton site.

Je n'ai jamais eu à me poser la question mais si cela devait te poser problème je suppose qu'il suffirait d'écrire un cookie lorsque le visiteur arrive sur la page (durée de vie à 0) et de vérifier son existence avant d'envoyer le mail Smiley murf ...

Ce qui compte avant tout est de bien vérifier les données POSTées avant de les traiter (ce qui semble être le cas).

A+
Salut Smiley smile

ça me rassure un peu. Je *crois* que mon formulaire est bien sécurisé (enfin...). En plus, il se trouve sur un serveur qui tourne avec mod_security, suphp et php-suhosin (si j'ai bien compris). Donc, à priori, pas de danger de hack (j'espère !)

Ce qui me turlupinait était de savoir si on pouvait en faire quelque chose à distance. A priori non, mais, comme tu me le conseille très justement, je pense que je vais utiliser un petit cookie histoire d'être sûr que c'est bien le formulaire du site qui est utilisé et pas une version traffiquée (quoique j'ai vu qu'on peut faire ce qu'on veut directement sur le site source avec WebDev)

Merci de ton aide Smiley smile
Tu peux aussi générer une clé aléatoire et la stocker dans la session... ex :

$_SESSION['form-key'] = md5(time());


Puis ajouter le champ :

<input type="hidden" name="key" value="{$_SESSION['form-key']}" />


Et enfin vérifier avant envoi que la clé est correcte :

if ($_POST['key'] != $_SESSION['form-key']) die("Dehors les trafiqueurs!");


C'est pas fiable à 100%, mais si on veut bidouiller ton formulaire de l'extérieur, il faut d'abord avoir une session valable... c'est toujours possible mais ça complique un peu la tâche.
Re',
Gasp75 a écrit :
...comme tu me le conseille très justement, je pense que je vais utiliser un petit cookie histoire d'être sûr que c'est bien le formulaire du site qui est utilisé et pas une version traffiquée...
Euh... non ! Je pense au contraire que c'est inutile Smiley smile !

De mon point de vue, seules les vérifications effectuées sur les variables POST qui sont reçues sont importantes et d'une manière générale je fais comme si le visiteur (sans même parler d'un éventuel hacker) pouvait saisir n'importe quoi dans une zone de saisie... et d'ailleurs il ne s'en prive pas Smiley biggol !

A+
yodaswii a écrit :
Ne pas oublier non plus que certains utilisateurs n'aiment pas les cookies. Smiley cligne
Ah oui au fait ! Ce serait quand même un comble de ne pas pouvoir poster parce que les cookies sont désactivés Smiley ravi !
Bonjour,
Heyoan a écrit :
De mon point de vue, seules les vérifications effectuées sur les variables POST qui sont reçues sont importantes et d'une manière générale je fais comme si le visiteur (sans même parler d'un éventuel hacker) pouvait saisir n'importe quoi dans une zone de saisie... et d'ailleurs il ne s'en prive pas Smiley biggol !

Tout à fait d'accord. Smiley smile

Pour aller plus loin, ne jamais oublier qu'il n'est pas si difficile que ça de créer une requête HTTP à la main. La seule chose importante est donc de bien vérifier les données reçues sur le serveur.
a écrit :
Je vous épargne les champs antispam


N'est-ce pas le role des tests de Turing type CAPTCHA d'empêcher la soumission automatique de formulaires? D'ou en découle la fonctionalité "anti-spam"...