8722 sujets

Développement web côté serveur, CMS

Pages :
Bonjour,
J'ai une réservation en ligne php, wamp, etc.
Un problème : qd la personne supprime sa réservation (à partir d'un lien sur le mail de confirmation qu'elle reçoit), ma bdd et espace-admin n'enregistrent pas cette annulation Smiley decu !
Configuration de ma réservation :
dossier site:
index.php (formulaire de résa)
bdd.php
annulation.php :
<?php
if($_GET['reservation']){
include('bdd.php');
$remove = $bdd->prepare('DELETE FROM reservations WHERE annulation = :annulation');
$remove->execute(array('annulation' => $_GET['reservation']));
$remove->closeCursor();
}else{
header('Location: index.php');
}
?>
+dossier backoffice avec index.php et supprimer.php (sans oublier les htaccess et htpassword)

Que me manque-t-il ?
Tout fonctionne par ailleurs...

Merci beaucoup pour votre aide,
bonne journée Smiley biggrin
Bonjour,

Je n'ai pas la solution à ton problème car je n'utilise plus PDO depuis un moment,
mais je voulais te mettre en garde sur ta requête...

Même si ta requête est sécurisée contre les injections car préparée, si quelqu'un s'amuse à modifier la variable GET pour y insérer un autre numéro, un autre client pourrait voir annuler sa réservation...

Je ne vois pas de contrôle dans ton code qui vérifie l'identité du client, mais je suppose que tu vérifies à un moment l'intégrité du client (avec par exemple une clé unique en GET)...
Bonjour, merci pour ta mise en garde ...mais suis très débutante et je ne comprends pas ce que je dois mettre à la place de _GET : un _POST ?
que mes conseilles-tu ? (à part supprimer la réservation en ligne Smiley ravi )
Autre question : c'est quoi "le contrôle dans ton code qui vérifie l'identité du client" ?? Smiley eek
Salut

Je pense que @ohweb veut parler d'un token qui est généré pour un utilisateur lors de sa réservation par exemple "40749cd366dda063b60d11e42fe937961bf". Ce qui fait que dans ton mail tu aura un lien de la sorte :

lienverslesite.com/annulation.php?reservation=34&token=40749cd366dda063b60d11e42fe937961bf

Il suffit de vérifier que le token correspond bien à celui de l'utilisateur qui a la réservation 34.

C'est comme le système des emails pour générer un nouveau mot de passe, si tu regarde il y a ton adresse mail + un token.
Le souci n'est pas d'utiliser GET au lieu de POST dans ce contexte, difficile de faire autrement puisque tes liens sont cliqués à partir d'un mail.

Mais imagine qu'un client n°49 un peu malicieux s'amuse à tester le lien en changeant id=49 par id=25, ta requête exécutera bêtement ce sur quoi le lien pointe, à savoir annuler la réservation numéro 25 si elle existe.

Autrement dit quelqu'un peut s'amuser à annuler toutes les réservations si cela lui chante, car tu ne testes pas si c'est bien le bon client qui annule la réservation.

Pour identifier un client de manière unique, j'imagine que tu as bien entendu un ID client en base, autrement dit si tu fais cela :
$remove = $bdd->prepare('DELETE FROM reservations WHERE annulation = :annulation [b]AND idClient = :idClient'[/b]);

Cela ira au moins s'assurer que la réservation appartient bien au client qui demande son annulation.

Mais ça n'empêchera pas la personne de modifier la variable idClient jusqu'à obtenir une requête qui permette d'annuler une réservation associé à l'id Client qu'il a saisi.

Pour une sécurité optimale, il faudrait associé chaque compte client (ou chaque réservation) à une clé générée aléatoirement (quelque chose de ce type par ex: fqdf1sqdfqsd4dq8g4ze1DKSj), que tu envoies dans le lien d'annulation en GET ainsi si quelqu'un souhaite annuler la réservation de quelqu'un d'autre, il en sera incapable car il ne possèdera pas la clé qui déclenche la requête DELETE...

A savoir quelque chose comme cela par ex :
$remove = $bdd->prepare('DELETE FROM reservations WHERE keyReservation = :keyMail AND idClient = :idClient');


Je ne sais pas si c'est très clair, en gros ce qu'il y a à retenir c'est qu'un ID est modifiable facilement, et permet d'exécuter des requêtes indésirables sur ta base de données à quelqu'un qui connait les bases du PHP, à savoir beaucoup de monde... et il suffit d'un seul.

Lorsque tu check l'unicité d'un client avec des variables de session cela fonctionne bien, mais lors d'un envoi par mail à quel moment checks-tu si le client est bien celui qui est censé déclencher la requête ?

Cela est une forme de faille CSRF, un article traitant de ce sujet :
http://venom630.free.fr/geo/tutz/securite_informatique/csrf.html

Edit :
John Wayne a écrit :
Je pense que @ohweb veut parler d'un token qui est généré pour un utilisateur lors de sa réservation par exemple "40749cd366dda063b60d11e42fe937961bf". Ce qui fait que dans ton mail tu aura un lien de la sorte :
lienverslesite.com/annulation.php?reservation=34&token=40749cd366dda063b60d11e42fe937961bf

C'est bien ça, je n'avais pas vu ton message Smiley smile
Modifié par ohweb (28 Apr 2014 - 13:05)
Merci beaucoup d'avoir pris le temps de m'expliquer avec code à l'appui la protection des réservations/annulation (il y a vraiment des gens qui n'auraient rien d'autre à faire ? Smiley lol )
Je vais appliquer tout de suite ...

mais cela n'empêche que qd il y a une annulation elle ne s'enregistre pas dans la bdd Smiley decu

Merci John et Ohweb Smiley ravi
ploll a écrit :
Merci beaucoup d'avoir pris le temps de m'expliquer avec code à l'appui la protection des réservations/annulation (il y a vraiment des gens qui n'auraient rien d'autre à faire ? Smiley lol )
Je vais appliquer tout de suite ...

mais cela n'empêche que qd il y a une annulation elle ne s'enregistre pas dans la bdd Smiley decu

Merci John et Ohweb Smiley ravi

Tu n'imagines pas à quel point un pirate peut être patient / persévérant en matière de malveillance... Smiley ohwell
De rien c'est toujours plus sûr, d'autant plus quand il y a des clients en jeu !

Pour ton problème de requête PDO, essaie peut-être avec la méthode bindValue(), je pense que les requêtes DELETE n'utilisent pas la même syntaxe que les autres,


<?php
	$remove->bindValue(':reservation', $_GET['reservation'], PDO: PARAM_INT);
	$remove->execute();
?>


j'ai trouvé ça ici :
http://www.experience-developpement.fr/php-pdo-requetes-preparees/#DELETE-prpar
Modifié par ohweb (28 Apr 2014 - 13:16)
ooh oui j'imagine ! mais... sur un site de petit restaurant ??!!
ou alors c'est entraînement pour pirate débutant Smiley lol
MERCI Smiley biggrin
Il vaut mieux prévenir que guérir, et aucun site n'est épargné quand il s'agit de s'amuser à ennuyer les gens ou simplement à exercer ses bases en hacking ^^

ps : j'ai édité mon post du dessus pour essayer de corriger ton problème avec PDO
Modifié par ohweb (28 Apr 2014 - 13:18)
Je bénéficie d'un accompagnement grand-luxe! Je découvre l'univers des forums et je suis épatée par cette entraide
Smiley biggrin
Ce n'est pas du luxe ^^ On est ici pour essayer d'aider comme on peut quand c'est dans notre domaine de compétence !

As-tu testé que cela fonctionnait ?
Je ne peux malheureusement pas tester, mais si cela ne fonctionne toujours pas peut-être qu'avec une variable tapée en dur au lieu du $_GET['reservation'], si cela fonctionne c'est que ça vient pas du code mais bien de la variable...
Modifié par ohweb (28 Apr 2014 - 14:02)
non pas encore testé car j'essaie de comprendre où dois-je mettre ce code (oui suis très débutante!)
Smiley cligne
La démarche que je suggère est la suivante :

- Dans ton formulaire pour réserver ajoute un input hidden avec un token, pour en générer un unique tu peux faire :

md5(uniqid(rand(), true))


Ce token tu peux le stocker en base dans ta table reservation.

- Après tu envoi ton email avec un lien du style

http://www.monsite.fr/annulation.php?idReservation=12&token=40749cd366dda063b60d11e42fe937961bf


- Dans ton fichier annulation.php tu fais les vérifications suivantes :

-- Regarde si tes GET sont bien remplis

-- Regarde si tu as bien un enregistrement pour l'id de reservation passé en paramètre AVEC le token lui aussi en paramètre.

-- Si tu as un résultat alors tu peux supprimer ta réservation

-- Sinon tu ne supprime et rien et tu peux informer l'utilisateur que sa réservation n'a pas été supprimée.
Bon, je vais me plonger dans la grammaire parce que là, je ne suis plus...
désolée j'avais de bons conseils ( Smiley biggrin mais ne sais pas trop comment faire pour les intégrer Smiley confused
le site est en construction donc pas en ligne.
je vais essayer d'avancer avec tous ces éléments...
Merci Smiley smile
Bonjour,

Le problème de l'id à la limite tu peux le mettre de côté je pense, ce n'est pas ton problème d'origine je t'ai un peu compliqué la vie pour rien ^^

Sinon j'ai réinstallé PDO ce matin et j'ai trouvé la solution à ton problème Smiley smile !
Ce code marche pour moi :
<?php
	$requete = "DELETE FROM reservations WHERE annulation = ?";
	$reponse = $bdd->prepare($requete);
	$reponse->execute(array($id));
?>

Il fallait donc utiliser la syntaxe "?" (ou en tout cas c'est une solution) au lieu de ":reservation" dans la requête.
Ensuite dans la ligne $reponse->execute(array($id)); , tu remplaces $id par ta variable $_GET['reservation'] et ça devrait fonctionner Smiley smile

Teste et dis moi si ça marche bien !
Modifié par ohweb (29 Apr 2014 - 11:04)
Bonsoir OhWeb! Absente et loin de mon ordi, j'avais un peu abandonné! Me revoilà et je lis ta soluce Smiley cligne ! Je vais essayer de ce clic! Smiley ravi
te tiens au courant
grand merci
Non ça ne marche pas, Smiley decu
mais où est donc l'erreur ? Smiley confused , ci-dessous mon code, ai-je oublié qque chose ?
<?php
if($_GET['reservation']){
include('bdd.php');
$remove = $bdd->prepare('DELETE FROM reservations WHERE annulation = ?');
$remove = $bdd->prepare('DELETE FROM reservations WHERE keyReservation = :keyMail AND idClient = :idClient');
$remove->execute(array($_GET['reservation']));
$remove->closeCursor();
}else{
header('Location: index.php');
}
?>

Avant j'avais
<?php
if($_GET['reservation']){
include('bdd.php');
$remove = $bdd->prepare('DELETE FROM reservations WHERE annulation = :annulation');
$remove = $bdd->prepare('DELETE FROM reservations WHERE keyReservation = :keyMail AND idClient = :idClient');
$remove->execute(array('annulation' => $_GET['reservation']));
$remove->closeCursor();
}else{
header('Location: index.php');
}
?>

Merci en tout cas de ton aide Smiley ravi
Bonjour,
Je ne suis pas un expert en PDO, mais je à mon avis, tu as 2 erreurs:
1) Tu écrases ta requête préparée: $remove est affectée 2 fois. Or, tu ne l'exécute qu'une fois. Pour faire 2 requêtes, il faudrait que ton algo ressemble plutôt à ça:
$remove = $bdd->prepare(ta première requete);
$remove-> execute(array(argument pour la requete));
$remove->closeCursor();

$remove = $bdd->prepare(ta seconde requete);
$remove-> execute(array(argument pour la requete));
$remove->closeCursor();

Mais là n'est pas la question, en fait, une seule requête devrait suffire pour ton problème... (Voir ci-après)

2) Tu exécutes une requete qui attends 2 arguments (keyMail et idClient), mais tu ne lui en passe qu'un seul dans ton execute. Donc forcément, il n'aime pas ^^

Pour le moment, contente toi d'une seule requete, tu n'as pas encore implémenté d'id de client ni rien, donc pour moi, ton code devrait ressembler à ça:

<?php
if($_GET['reservation']){
include('bdd.php');
$remove = $bdd->prepare('DELETE FROM reservations WHERE annulation = ?');
$remove->execute(array($_GET['reservation']));
$remove->closeCursor();
}else{
header('Location: index.php');
}
?>

Une fois que l'on sera sûrs que ce code fonctionne, on pourra s'attaquer aux id uniques de clients Smiley cligne
Bon courage à toi en tout cas!
Pages :