Protéger un formulaire contre le detournement commande DOS

tiokaz
Invité n'ayant pas de compte PHPfrance

03 janv. 2013, 16:15

Bonjour Messieurs et Mesdames.

Voila je fait appel à vous , à vos compétences qui me dépasse encore un peu :)
J'ai créé un site pour une personne, cette personne est un bidouilleur et il vient de me poser une colle et je n'aimerai ne pas perdre la face devant lui.
Bref passons aux choses sérieuses... Sur ce site j'ai mis en place un formulaire de contact en PHP envoyant un email à la personne selectionnée dans le formulaire, il est securisé par du script PHP contre les envois vide, contre les emails invalides... et hier je reçois un mail me disant qu'il à réussi à detourner mon formulaire avec cette commande DOS ( pour des raisons évidente de confidentialité les information personnel seront remplacées par des XXX )
curl -x XXX.XXX.XXX.XXX:8080 -X POST -d "choixMail=XXX%40XXX.fr&son_prenom=XXX&son_nom=XXX&societe=&te=&son_email=test%40test.com&mess=test&envoyer=Envoyer" www.XXX.fr/contact.php
et donc il me demande de le protéger face à ce genre d'attaque
Ma question principale coule de source , comment protéger ce formulaire face à ce genre de détournement?
La secondaire est ce réellement utile ? quels sont les risques si le formulaire reste non securisé ?

D'avance merci

ViPHP
ViPHP | 928 Messages

03 janv. 2013, 16:34

Bonjour,
concrètement la seule chose qu'il peut faire c'est envoyer un formulaire vers votre serveur, en mettant les valeurs qu'il veut. Cela implique deux choses :

1. Il peut mettre des valeurs farfelues, c'est à dire que si vous aviez un champ de type "select" avec deux choix, il pourrait très bien entrer une valeur farfelue au lieu des deux choix possibles.
Les risques sont que vous obteniez des soucis de logiques dans votre script, ou qu'il tente de faire des injections SQL. Pour éviter cela il faut simple vérifier les valeurs reçues, c'est à dire bien vérifier que la valeur envoyée pour votre champ de type "select" correspond bien à une des deux attendue, ou bien protéger vos requêtes SQL avec des mysql_real_escape_string() ou des requêtes préparées PDO.

2. Il peut soumettre le formulaire autant de fois qu'il le veut, donc concrètement il peut flooder votre serveur mail s'il soumet le formulaire 1000 fois en quelques secondes par exemple.
Pour éviter ce genre de soucis, vous pouvez par exemple ajouter un sleep(1) avant l'envoie du mail, ou bien stocker l'IP du client quelque part et bannir l'IP s'il tente de soumettre le formulaire un certain nombre de fois dans un laps de temps (par exemple un mec qui enverra 10 fois le formulaire en moins d'une minute).

Cordialement

ViPHP
ViPHP | 2577 Messages

03 janv. 2013, 17:07

Une possibilité est de renseigner une variable de session lors de l'affichage du formulaire et de la remettre à vide lors de l'envoi du mail.
Il est ainsi possible de lier l'affichage du formulaire et l'envoi du mail et d'empêcher les refresh.

tiokaz
Invité n'ayant pas de compte PHPfrance

03 janv. 2013, 17:59

Merci pour vos réponses et votre réactivité, en lisant vos 2 posts j'ai plus appris qu'en une demi journe de recherche sur le web ^^
Effectivement dans la demonstration du Hack de mon formulaire il a remplacé l'adresse mail du destinaire par la mienne donc il est bien en mesure changer les infos contenu dans mon <select>

Donc sauf erreur de ma part je n'ai pas lié le formulaire a une base de donné, les infos sont retranscritent directement dans un mail sans passer par la case BDD
donc le seul danger c'est qu'un hacker se serve de mon formulaire pour du flood ou du mail bombing ?

En sachant que je n'ai pas de base donnée derriere la quel de ces methode me conseillez vous ?

Encore merci pour cette aide

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

03 janv. 2013, 18:49

Un contrôle des données reçues avant tout traitement reste la règle numéro 1 (et à priori celle à utiliser de toute façon, que tu sois en train d'envoyer des mails, écrire dans une base, passer des commandes ou faire quoi que ce soit d'autre).

En gros, si ton formulaire de mail ne peut être adresser qu'à une seule adresse mail : faut pas la montrer. PHP pourra l'ajouter au moment voulu sans que l'utilisateur n'ait la main ni même de visibilité dessus.

Si l'utilisateur doit choisir dans la liste la ou les personnes à qui adresser la demande il faut simplement t'assurer côté php que les adresses envoyées sont bien autorisées. Pour faire simple, il suffit d'un tableau d'adresses mail valide et un simple inArray() pour vérifier que l'adresse de choixMail se trouve bien dedans, sinon tu arrêtes le traitement et renvoi un message d'erreur.

Pour faire mieux dans ce cas précis, au lieu d'adresse mail visible, tu utilises des constantes (1 = admin, 2 = hotline, 3 = reine elisabeth, ...). Côté client, dans le source de ta page il ne verra que les codes 1, 2 ou 3, et toi côté php tu as juste à remplacer si la valeur reçu est 3, alors le mail est envoyé à [email protected] (que l'utilisateur ne verra jamais et ne pourra donc jamais altéré. Toute autre valeur renvoyant une erreur ou à défaut n'envoyant pas de mail :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
ViPHP | 2577 Messages

04 janv. 2013, 15:15

Il faut vérifier que les variables utilisées dans le mail ne comportent pas de retour à la ligne (\n) enfin sauf le contenu du mail.
Les \n peuvent être utilisés pour modifier les entêtes du mail.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

04 janv. 2013, 15:50

pour completer je te dirais que sans code on ne peux aller plus loin que te demander si tu utilise la fonction empty, ou bien une comparaison avec une chaîne pour déterminer la validité des champs.

je parle d'empty, pour bien signifier que cette vérification doit être faite en PHP, si fait la vérification en JS, c'est un e"confort" pour l'utilisateur mais en aucun cas une preuve, coté serveur, que le champs sera réellement remplis.
et notamment dans le cas que tu indique (utilisé par des robots a spam par exemple ;) ).


@+
Il en faut peu pour être heureux ......