Formulaires et php : ne rien oublier

Un champ de type input où un utilisateur est amené à le remplir avec des valeurs numériques et un script php mal configuré peuvent engendrer, pour le site concerné, de sérieux problèmes selon l’importance de ce champ.

Pourquoi ? Prenons tout simplement l’exemple d’un webmaster qui propose à ses membres de faire une donation au site de leurs points gagnés à des jeux. Le membre se retrouve donc confronté à un champ input où il entre le montant en points qu’il désire donner… ou pas, si le script comporte une faille. Regardons par exemple ce script :

$pseudo = $membre['pseudo']; // nom de compte du membre
$points = $membre['points']; // points du membre
$don = intval($_POST['champ_input_de_don']); // don du membre
mysql_query("UPDATE table_membres SET points=points-$don WHERE pseudo='$pseudo'"); // on enlève les points au membre
echo "Merci de votre générosité, vous avez donné $don Points.";

Vous ne voyez rien ? La variable $don est bien protégée par un intval() mais il reste un problème. Car, même si ce code est opérationnel, il contient un gros problème. Prenons ainsi l’exemple du membre qui compte utiliser ce formulaire de dons pour, au contraire, gagner des points. Comment procède-t-il ? Tout simplement en offrant une valeur négative de points… Par exemple, le membre au nom de mechantvilain offre -10 Points. Le code exécuté est donc le suivant :

mysql_query("UPDATE table_membres SET points=points--10 WHERE membre='mechantvilain'"); // on enlève les points au membre
echo "Merci de votre générosité, vous avez donné -10 Points.";

Et voilà, le don empoisonné, car vous savez que – par – donne +, soit une hausse de 10 points du compte du membre. Cela peut coûter très cher au webmaster d’un site si jamais il ne s’en rend pas compte rapidement, alors que la sécurisation est pourtant très simple, il suffit de rajouter une condition « if » à notre script :

if($don>0) { // on exécute la requête de don } elseif($don==0) { echo "Vous n'avez donné aucun point"; } else { echo "Vous ne pouvez pas donner une valeur négative de points !"; }

Et avec le code complet, on a :

$pseudo = $membre['pseudo']; // nom de compte du membre
$points = $membre['points']; // points du membre
$don = intval($_POST['champ_input_de_don']); // don du membre
if($don>0)
{
mysql_query("UPDATE table_membres SET points=points-$don WHERE pseudo='$pseudo'"); // on enlève les points au membre
echo "Merci de votre générosité, vous avez donné $don Points.";
}
elseif($don==0)
{
echo "Vous n'avez donné aucun point";
}
else
{
echo "Vous ne pouvez pas donner une valeur négative de points !";
}

Et voilà… :) Avec ce script, vous avez largement de quoi corriger un autre bug volontaire… En effet, dans notre code, il manque une condition permettant de donner des points seulement si le membre en a suffisamment, le cas échéant, par sa trop grande générosité, c’est lui qui se retrouvera cette fois-ci avec un solde de points négatifs. Bonne chance et n’hésitez pas à poster vos propositions. ;)

1 commentaire

  1. CodeGratuit a écrit,

    le 24 mars 2012 @ 10:06

    Bonjour,
    Suite à la lecture de cet article je me rend compte que parfois la moindre petite erreur peut coutée cher !
    Cet article m’a permis de corriger celle-ci non pas une fois fois, mais DEUX fois !
    Je vais parcourir poweb d’un peu plus près et voir si ce que je recherche ne s’y trouve pas !
    Un gros merci en tout cas !
    Bien amicalement, Yann.