Protéger votre formulaire de contact contre les spammers et hackers

La solution idéale pour être contacté par les utilisateurs de votre site, sans publier votre adresse email, qui deviendrait vite une proie facile pour les spammers, est d’utiliser un formulaire de contact. Il y a d’autres solutions anti spam, mais celle-ci a aussi l’avantage, en plus de paraitre professionnelle, d’offrir un moyen d’être contacté par des visiteurs qui ne peuvent accéder à leur logiciel ou service email lors de leur visite. Toutefois, un formulaire n’est pas complètement invulnérable, à moins de prendre certaines précautions.

La première, est, évidemment, de ne pas publier votre adresse contact dans les champs cachés de votre formulaire, car ça la rends tout aussi vulnérable que si vous la publiez en mode texte. Il ne faut inscrire cette adresse que dans une variable du script qui traite l’envoi du message. Je déconseille aussi vivement l’emploi de logiciels populaires pour traiter l’envoi du formulaire, car ceux-ci deviennent vite la cible des spammers comme le code est public.

Une autre précaution est de vérifier que votre script n’est pas exploité pour envoyer du spam aux autres, ou pire, des virus, à cause d’une vulnérabilité aux attaques par injection. Ce problème pourrait ajouter votre site dans les listes noires (blacklist) du monde comme source de spam et, en plus du risque de voir son compte d’hébergement annulé, vous pourriez ne plus être capable d’envoyer des emails à bien du monde, possiblement un client riche et célèbre.

Voici comment faire:

if (eregi("MIME-Version:|Content-Type:|Content-Transfer-Encoding:|bcc:|cc:", $email . $message)) {
exit("Tentative d'intrusion détectée");
}

Dans cette instruction, on cherche quelques morceaux de code, tel que MIME-Version: ou bcc:, qui sont souvent « injectés » lors d’un accès direct aux variables de votre script afin de le détourner de sa fonction première pour envoyer du spam aux autres. Mon exemple vérifie $email et $message, mais vous devriez insérer toutes les variables qui sont utilisées dans votre fonction php mail().

Très souvent, les spammers incluent du code html typique dans le message pour promouvoir leurs sites, comme href ou [url]. On peut encore une fois vérifier si le contenu de nos variables n’incluent pas ces indices révélateurs:

if(eregi("href|\[url\]", $message)) {
exit("Nous ne permettons pas de liens html dans les messages.");
}

Certains webmasters vont aussi vérifier si le référant (referer) du navigateur indique bien que l’accès au script provient de la page contenant le formulaire, puisque les spammers accèdent généralement à la page script directement, mais je ne conseille pas vraiment cette méthode parce qu’une bon pourcentage des visiteurs légitimes ne fournissent pas non plus le référant du à la configuration de leur navigateur, de leur logiciel anti-virus ou leur firewall, et pourrait se trouver dans l’impossibilité de vous contacter. Tout de même, je peux publier les grandes lignes de la méthode:

$referer = $_SERVER["HTTP_REFERER"]; 
if ($referer) {
	$domain = parse_url($referer);
	if ($domain["host"] != "www.example.com") exit("Votre référant ne provient pas de notre site");
}
else exit("Nous ne pouvons pas détecter votre référant");

En quelques mots, on vérifie le référant, et s’il existe, on compare son nom de domaine au nom de domaine de notre site, dans ce cas www.example.com (insérer le vôtre dans votre code), et si le référant ne provient pas de notre site, ou si nous ne pouvons obtenir de référant, on arrête le script. À utiliser en cas vraiment nécessaire seulement.

Les méthodes prochaines sont un peu plus compliquées, mais fournissent une protection presque totale. Je n’ai jamais eu de problème depuis plusieurs années grâce à celles-ci. En fait, j’ai hésité à les publier parce qu’elles marchent tellement bien, si elles devenaient populaires, les spammers et hackers pourraient trouver une façon des les contourner. Mais bon, les bonnes choses doivent être partagées.

Le principe de la méthode suivante est de vérifier si la valeur d’un champs caché a bien été modifiée par une fonction javascript de validation. En effet, la plupart des logiciels employés par les spammers et les hackers ne sont pas capables (jusqu’à maintenant) d’interpréter Javascript.

En premier lieu, on va remplacer le bouton typique de soumission dans le formulaire:

par un bouton normal qui va utiliser une fonction javascript pour activer la soumission du formulaire:

La partie formulaire des morceaux document.formulaire et formulaire.submit() devrait être le nom que vous donner à la balise:

Ajoutez un champs caché juste après la balise form, comme suit:

Mettez la fonction javascript valider() dans les headers, comme tout code javascript contenu dans une page. Nous allons en profiter pour valider le reste du formulaire afin de s’assurer que tous les champs sont bien remplis, ce qui est une pratique courante et vous épargnera les messages vides envoyés par des utilisateurs débutants qui ne peuvent s’empêcher de cliquer les boutons sur une page avant de savoir à quoi ils servent:


Ce script n’est pas très compliqué, comme vous pouvez le constater, il vérifie si les champs de notre formulaire sont remplis, et on en profite pour donner la valeur test_reussi (ça pourrait être n’importe quoi d’autre) au champs vide securite.

Ensuite, dans votre script de traitement du formulaire, il suffit de vérifier si la valeur est bel et bien celle que nous lui avons donné avec notre code de validation javascript:

if ($_POST["securite"] != "test_reussi") exit("Tentative d'intrusion détectée");

Et voilà! Votre formulaire de contact devrait être à toute fin pratique invulnérable aux attaques ordinaires.

En fait, si vous avez un petit coté paranoïaque, vous pouvez aussi ajouter une autre fonction, bien que jusqu’ici, vous devriez être franchement barricadé. Comme les attaques sont souvent automatisées par des logiciels qui remplissent tous les champs du formulaire pour passer les test courants de vérification, ou pour injecter leur code malfaisant, on peut aussi ajouter un champs vide caché, et vérifier dans le script si celui-ci a été rempli avec une valeur quelconque, alors qu’elle devrait être restée vide, et rejeter la requête dans ce cas. Exemple:

Ensuite, dans le script:

if ($_POST["vide"] != "") exit("Tentative d'intrusion détectée");

4 thoughts on “Protéger votre formulaire de contact contre les spammers et hackers

  1. Bonjour,

    Je suis un peu surpris que vous donniez une telle importance au javascript, et d’autant plus que les spammeurs savent parfaitement le contourner comme j’avais pu m’en rendre compte lorsque les formulaires (et les forums !) semblaient-être devenus leur terrain de chasse (vers 2005/ 2006, ou 2007, je sais plus bien) !

    Je dis bien : « le contourner », c’est-à-dire faire – je ne sais comment – comme s’il n’était PAS LÀ, et quoiqu’il semble pouvoir « barricader » !

    La seule méthode qui me paraît efficace consiste à réserver le javascript aux utilisateurs « honnêtes » et parfois distraits (champs bien remplis par exemple) puis si tout va bien aller faire un tour côté serveur :

    <form action="verification.php" method=etc.

    Ce fichier "verification.php" pourra alors s'occuper PAR SCRIPT PHP de faire tout le boulot d'élimination côté serveur et envoyer bouler les indésirables !

    Sur mon site, j'ai même ajouté une sécurité supplémentaire : en fait, ce fichier "verification.php" n'envoit PAS le message au clic du visiteur, il est enregistré dans la Base (le bouton "Envoyer" ne s'appelle pas "Envoyer" mais "Recevoir une validation d'envoi") !

    Et donc un message de validation est envoyé immédiatement À L'EXPÉDITEUR qui, après réception, devra cliquer sur un lien pour envoyer EFFECTIVEMENT son message !

    De ce fait, les expéditeurs voyous ou mauvais plaisantins qui indiquent de "fausses" adresses (ou l'adresse de quelqu'un d'autre par sinistre plaisanterie) sont également éliminés : leur message reste dans la Base qui les efface automatiquement après x jours !

    Cordialement

  2. Daniel a dit :
    ….
    Et donc un message de validation est envoyé immédiatement À L’EXPÉDITEUR qui, après réception, devra cliquer sur un lien pour envoyer EFFECTIVEMENT son message !
    ….

    Bien! :-) … Comme ca ton formulaire de contact peut servir à envoyer des mails à n’importe qui, tu deviens toi-même un spammeur en puissance…

  3. halexy a dit :
    ….
    Comme ca ton formulaire de contact peut servir à envoyer des mails à n’importe qui, tu deviens toi-même un spammeur en puissance…
    ….

    Tu n’as pas compris, halexis !

    1) Le pourrielleur n’enverra RIEN si son commentaire comporte des mots interdits, car bien sûr mon PHP commence par :
    if(stristr($message,’http’) || stristr($message,’pills’) || stristr($message,’xxx’) j’en ai une quinzaine comme ça…

    2) Si par hasard son message est « bénin » (donc, quel intérêt pour lui ???), il est envoyé, UNIQUEMENT, à…. ma Base MySql !

    3) Le bouton « envoyer » n’indique pas « envoyer » mais : « recevoir une validation d’envoi ».

    Il aura donc le GRAND plaisir (tu parles !) de SAVOIR que sa « victime » va recevoir un courriel (qu’il ne connaîtra lui-même jamais) indiquant (en gros) : « Merci pour votre message – Cliquez sur (ce lien) pour me l’envoyer – Ignorez cette confirmation si un mauvais plaisant s’est fait passer pour vous en indiquant votre adresse ».

    De toute façon, son petit jeu ne durerait pas longtemps s’il persistait (s’il est débile, donc) : ses messages RESTANT bien au chaud dans ma Base, crois-tu que je resterais inactif en les trouvant ???
    Dans les 24 h, son IP serait enregistré, et, CROIS-MOI, il serait le 1er à l’apprendre en recommençant (ou plutôt en essayant de) son petit jeu !

    En tout cas, depuis 7 ans maintenant que j’utilise ce système, aucun pourrielleur ne s’y est amusé pour mon site pourtant relativement assez visité dans le monde : 3 785 679 visiteurs à cet instant.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *