Sécurité AJAX avec enregistrement dans la base de donnée
Fermé
adamantyn
Messages postés
7
Date d'inscription
dimanche 8 mars 2015
Statut
Membre
Dernière intervention
17 juin 2019
-
Modifié le 16 juin 2019 à 13:52
adamantyn Messages postés 7 Date d'inscription dimanche 8 mars 2015 Statut Membre Dernière intervention 17 juin 2019 - 17 juin 2019 à 11:59
adamantyn Messages postés 7 Date d'inscription dimanche 8 mars 2015 Statut Membre Dernière intervention 17 juin 2019 - 17 juin 2019 à 11:59
A voir également:
- Sécurité AJAX avec enregistrement dans la base de donnée
- Tnt base de données vide ✓ - Forum TNT / Satellite / Réception
- Formules excel de base - Guide
- Mode securite - Guide
- Url masquée pour votre sécurité - Forum Programmation
- Célia doit nettoyer le tableau ci-dessous pour l’ajouter à la base de données de son entreprise. les données sont ensuite traitées automatiquement. quelles sont les 4 cellules qui risquent de poser problème ? ✓ - Forum Excel
3 réponses
tpez
Messages postés
330
Date d'inscription
lundi 4 juillet 2016
Statut
Membre
Dernière intervention
17 juin 2019
39
16 juin 2019 à 15:55
16 juin 2019 à 15:55
Bonjour,
Je ne connais pas vraiment le contexte de ton application, mais quelques éléments de ton code semblent représenter un rique.
Pour commencer je vais faire un petit rappel sur les tech que tu utilises :
- Le JS / AJAX est exécuté côté client, par conséquent le code ajax est directement lisible/éditable depuis la console navigateur via le débugger par exemple.
- Le PHP lui est exécuté côté serveur, de ce fait aucun code php n'est lisible par le client.
Voilà un problème pour commencer :
-
Aucune action critique, ne doit être effectuer dans JS.
Pour la suite il me faudrait d'autres informations tel que :
- Comment sont définis les variables :
- newQuantity
- cart_id (quel est le but de cette variable)
- A quoi resemble ta base de données ?
- Tables
- Colonnes des tables
- Y a t-il des informations personnelles stockées sur la DB ?
- A quoi resemble le front ?
- Code html
- L'application a t-elle recours à des méthodes d'authentifications (SESSIONS, JWT...)?
- Si tu développes sur un serveur accessible peux-tu nous communiquer l'adresse url pour simplifier l'audit ?
Je ne connais pas vraiment le contexte de ton application, mais quelques éléments de ton code semblent représenter un rique.
Pour commencer je vais faire un petit rappel sur les tech que tu utilises :
- Le JS / AJAX est exécuté côté client, par conséquent le code ajax est directement lisible/éditable depuis la console navigateur via le débugger par exemple.
- Le PHP lui est exécuté côté serveur, de ce fait aucun code php n'est lisible par le client.
Voilà un problème pour commencer :
-
data : "cart_id="+cart_id+"&new_quantity="+newQuantity+"&member_id="+<?php echo $member_id?>Il y a baucoup à dire sur cette unique ligne de code. Ceci est modifiable par l'utilisateur ! Il peut donc directement changer "cart_id", "newQuantity" dans le code javascript mais cela n'est pas forcément un problème, le plus gros problème réside dans le "member_id" quelqu'un pourrait aisément changer ce member_id pour ajouter un article à un autre client !
Aucune action critique, ne doit être effectuer dans JS.
Pour la suite il me faudrait d'autres informations tel que :
- Comment sont définis les variables :
- newQuantity
- cart_id (quel est le but de cette variable)
- A quoi resemble ta base de données ?
- Tables
- Colonnes des tables
- Y a t-il des informations personnelles stockées sur la DB ?
- A quoi resemble le front ?
- Code html
- L'application a t-elle recours à des méthodes d'authentifications (SESSIONS, JWT...)?
- Si tu développes sur un serveur accessible peux-tu nous communiquer l'adresse url pour simplifier l'audit ?
adamantyn
Messages postés
7
Date d'inscription
dimanche 8 mars 2015
Statut
Membre
Dernière intervention
17 juin 2019
Modifié le 16 juin 2019 à 16:44
Modifié le 16 juin 2019 à 16:44
Merci,
-cart_id : est une variable qui va sélectionner un id dans la DB côté serveur.
-la base de donnée a une table product et une table cart, avec les champs :
id
product_id
quantity
member_id
-Oui il y aura des informations personnelles dans la DB
-Il y aura une méthode d’authentification, la variable member_id aura le numéro de l'utilisateur
-Désolé je développe en local
Voilà le code complet du front, le back est déjà posté(update_cart_quantity.php):
-cart_id : est une variable qui va sélectionner un id dans la DB côté serveur.
-la base de donnée a une table product et une table cart, avec les champs :
id
product_id
quantity
member_id
-Oui il y aura des informations personnelles dans la DB
-Il y aura une méthode d’authentification, la variable member_id aura le numéro de l'utilisateur
-Désolé je développe en local
Voilà le code complet du front, le back est déjà posté(update_cart_quantity.php):
<?php require 'connectDB.php'; $member_id = 2; ?> <html> <head> <title>Shopping Cart</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="style.css" type="text/css" rel="stylesheet" /> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <script src="jquery-3.2.1.min.js"></script> <script> function save_to_db(cart_id, newQuantity) { $.ajax({ url : "update_cart_quantity.php", data : "cart_id="+cart_id+"&new_quantity="+newQuantity+"&member_id="+<?php echo $member_id?> , type : 'post', dataType: "json", success : function(response) { if(response === "Empty cart"){ $("#total-quantity").text(0); $("#total-price").text(0); $("#shopping-cart-table").html("<h2><b style='color:red'>Your cart is empty.</b></h2>"); } if(newQuantity == 0){ $("#item-container-"+cart_id).remove(); } var totalQuantity = 0; var totalItemPrice = 0; $.each(response, function(key, cartDetails) { totalItemPrice = totalItemPrice + parseInt(cartDetails.price) * parseInt(cartDetails.quantity); totalQuantity = totalQuantity + parseInt(cartDetails.quantity); if(cartDetails.cart_id == cart_id){ $("#input-quantity-"+cart_id).val(cartDetails.quantity); $("#cart-price-"+cart_id).text("$"+cartDetails.price * cartDetails.quantity); } }); $("#total-quantity").text(totalQuantity); $("#total-price").text(totalItemPrice); $("#total-price-foot").text(totalItemPrice); } }); } </script> </head> <body> <?php $db_query = mysqli_query($conn,"SELECT tbl_product.*, tbl_cart.quantity, tbl_cart.id as cart_id FROM tbl_product, tbl_cart WHERE tbl_product.id = tbl_cart.product_id AND tbl_cart.member_id = ".$member_id.""); while ($row = $db_query->fetch_assoc()) { $cartItem[] = $row; } $item_quantity = 0; $item_price = 0; if (! empty($cartItem)) { foreach ($cartItem as $item) { $item_quantity = $item_quantity + $item["quantity"]; $item_price = $item_price + ($item["price"] * $item["quantity"]); } } ?> <!--Shopping cart header--> <div id="shopping-cart"> <div class="txt-heading"> <div class="txt-heading-label"><a href='index.php' style="text-decoration: none">Shopping Cart</a></div> <div class="cart-status"> <?php if (! empty($cartItem)) {?> <div id="total-quantity"><?php echo $item_quantity; ?></div> <div> <strong>$</strong> <strong id="total-price"><?php echo $item_price; ?></strong> </div> <?php } ?> </div> <a id="btnCart" href="cart.php" class="float-right"> <i class="material-icons" alt="Cart" title="Cart">shopping_cart</i> </a> </div> <?php if (! empty($cartItem)) { ?> <!--Shopping cart table--> <div id="shopping-cart-table" class="shopping-cart-table"> <div class="cart-item-container header"> <div class="cart-info title">Title</div> <div class="cart-info options">Options</div> <div class="cart-info quantity">Quantity</div> <div class="cart-info unit-price">Unit price</div> <div class="cart-info price">Price</div> </div> <?php foreach ($cartItem as $item) { ?> <div id="item-container-<?php echo $item["cart_id"]; ?>" class="cart-item-container"> <div class="cart-info title"> <a href="" style="text-decoration:none"><img src='<?php echo $item["image"]; ?>' width="50" height="40" style="border-radius:50%" /> <?php echo $item["name"]; ?></a> </div> <div class="cart-info options"> <form method='post' action=''> <select name='taille'> <option value="S">S</option> <option value="M">M</option> <option value="L">L</option> <option value="XL">XL</option> <option value="XXL">XXL</option> </select> </form> </div> <div class="cart-info quantity"> <div class="btn-increment-decrement" onClick="save_to_db(<?php echo $item["cart_id"]; ?>, -1)"><i class="material-icons">remove_circle_outline</i></div> <input class="input-quantity" id="input-quantity-<?php echo $item["cart_id"]; ?>" value="<?php echo $item["quantity"]; ?>" readonly> <div class="btn-increment-decrement" onClick="save_to_db(<?php echo $item["cart_id"]; ?>, 1)"><i class="material-icons">add_circle_outline</i></div> </div> <div class="cart-info unit-price"> <?php echo "$". ($item["price"]); ?> </div> <div class="cart-info price" id="cart-price-<?php echo $item["cart_id"]; ?>"> <?php echo "$". ($item["price"] * $item["quantity"]); ?> </div> <div class="cart-info action"> <div class="btn-increment-decrement" onClick="save_to_db(<?php echo $item["cart_id"]; ?>, 0)"><i class="material-icons" alt="Delete" title="Remove Item">delete</i></div> <div> Delete </div> </div> </div> <?php } ?> <div id="shopping-cart-footer" class="cart-item-container footer"> <div class="cart-info title">Total</div> <strong>$ <strong id="total-price-foot"><?php echo $item_price; ?></strong></strong> </div> <?php } ?> </div> </div> </body> </html>
tpez
Messages postés
330
Date d'inscription
lundi 4 juillet 2016
Statut
Membre
Dernière intervention
17 juin 2019
39
16 juin 2019 à 21:46
16 juin 2019 à 21:46
Bon alors selon moi, Oui il y a des problèmes de sécurité.
Premièrement il est absolument nécéssaire d'utiliser un système comme JWT pour vérifier que l'ajout du produit pour un utilisateur ne vienne pas d'un autre utilisateur.
Grossièrement sans token (jeton JWT) :
Nous avons deux clients (ClientA, ClientB).
ClientA se connecte, change son membre_id par celui du ClientB dans le JS et ajoute un objet.
Par conséquent ClientB obtient un produit dans son panier alors qu'il ne l'a jamais ajouté.
Avec un jeton JWT :
Nous avons deux clients (ClientA, ClientB).
ClientA se connecte, obtient un JWT et change son membre_id par celui du ClientB dans le JS et ajoute un objet.
Seulement nous faisons une vérification de membre_id avec le Jeton en question et l'on s'aperçoit que ClientB ne possède pas le token qui a été utilisé pour ajouter le produit.
Par conséquent l'objet n'est pas ajouté au panier.
Mais même si tu ajoutes un système de token actuellement cela ne changerait pas grand chose car aucun filtre n'est appliqué du côté serveur, il est donc possible de faire une injection SQL pour contourner le système de token, ou pour lire la base de données.
Mon conseil est le suivant :
Utiliser un framework comme laravel qui gère les systèmes de token JWT nativement et qui permet d'appliquer des filtres sur des forms et les requêtes SQL pour éviter les injections.
Premièrement il est absolument nécéssaire d'utiliser un système comme JWT pour vérifier que l'ajout du produit pour un utilisateur ne vienne pas d'un autre utilisateur.
Grossièrement sans token (jeton JWT) :
Nous avons deux clients (ClientA, ClientB).
ClientA se connecte, change son membre_id par celui du ClientB dans le JS et ajoute un objet.
Par conséquent ClientB obtient un produit dans son panier alors qu'il ne l'a jamais ajouté.
Avec un jeton JWT :
Nous avons deux clients (ClientA, ClientB).
ClientA se connecte, obtient un JWT et change son membre_id par celui du ClientB dans le JS et ajoute un objet.
Seulement nous faisons une vérification de membre_id avec le Jeton en question et l'on s'aperçoit que ClientB ne possède pas le token qui a été utilisé pour ajouter le produit.
Par conséquent l'objet n'est pas ajouté au panier.
Mais même si tu ajoutes un système de token actuellement cela ne changerait pas grand chose car aucun filtre n'est appliqué du côté serveur, il est donc possible de faire une injection SQL pour contourner le système de token, ou pour lire la base de données.
Mon conseil est le suivant :
Utiliser un framework comme laravel qui gère les systèmes de token JWT nativement et qui permet d'appliquer des filtres sur des forms et les requêtes SQL pour éviter les injections.
adamantyn
Messages postés
7
Date d'inscription
dimanche 8 mars 2015
Statut
Membre
Dernière intervention
17 juin 2019
Modifié le 16 juin 2019 à 23:31
Modifié le 16 juin 2019 à 23:31
Merci pour votre réponse.
Je vais intégrer la panier à un site plus important qui n'est pas écrit avec un framework. Donc ça me paraît difficile d'utiliser cette solution.
Si l'utilisateur s'est connecté avec son mon de passe et identifiant, et que le
J'ai aussi essayer de changer
Je poste le lien d'un exemple, est-ce que vous pourriez me montrer comment vous ajoutez un produit à un nouvel utilisateur, '1' ou '3' par exemple? L'utilisateur actuel étant le numéro '2'.
https://adamantin.000webhostapp.com/tests/cart-custom/cart.php
Voilà à quoi ressemble la DB:
id product_id quantity member_id
54 1 1 2
56 3 1 2
57 2 1 2
Je vais intégrer la panier à un site plus important qui n'est pas écrit avec un framework. Donc ça me paraît difficile d'utiliser cette solution.
Si l'utilisateur s'est connecté avec son mon de passe et identifiant, et que le
member_idest écrit en php, donc côté serveur, et prend le numéro de la session, comment il peut être changé, je ne comprends pas?
J'ai aussi essayer de changer
le cart_iddirectement dans l'inspecteur, ca ne fonctionne pas, le résultat d'une opération est toujours ce que l'on espère, donc pas de hack
Je poste le lien d'un exemple, est-ce que vous pourriez me montrer comment vous ajoutez un produit à un nouvel utilisateur, '1' ou '3' par exemple? L'utilisateur actuel étant le numéro '2'.
https://adamantin.000webhostapp.com/tests/cart-custom/cart.php
Voilà à quoi ressemble la DB:
id product_id quantity member_id
54 1 1 2
56 3 1 2
57 2 1 2
tpez
Messages postés
330
Date d'inscription
lundi 4 juillet 2016
Statut
Membre
Dernière intervention
17 juin 2019
39
17 juin 2019 à 00:16
17 juin 2019 à 00:16
Il y a une partie que je ne saisie pas... Comment l'application sait que je suis le client "2" sur cette page ?
https://adamantin.000webhostapp.com/tests/cart-custom/index.php
Je ne me suis pas enregistré en tant que tel et ce n'est pas non plus en cookie, alors comment l'application sait que je suis client "2" ?
D'autre part le fait de passer une commande en GET comme suit :
?action=add&code=wristWear03 est à proscrire car c'est également un problème de sécurité (campagne de phishing ajoutant un objet au panier) de plus le simple fait de recharger la page provoque l'ajout de l'objet dans le panier.
https://adamantin.000webhostapp.com/tests/cart-custom/index.php
Je ne me suis pas enregistré en tant que tel et ce n'est pas non plus en cookie, alors comment l'application sait que je suis client "2" ?
D'autre part le fait de passer une commande en GET comme suit :
?action=add&code=wristWear03 est à proscrire car c'est également un problème de sécurité (campagne de phishing ajoutant un objet au panier) de plus le simple fait de recharger la page provoque l'ajout de l'objet dans le panier.
tpez
Messages postés
330
Date d'inscription
lundi 4 juillet 2016
Statut
Membre
Dernière intervention
17 juin 2019
39
17 juin 2019 à 00:27
17 juin 2019 à 00:27
Je viens de trouver comment est défini l'utilisateur mais dans un cas concrèt il ne serait pas défini dans le code PHP en brute alors est-il possible d'ajouter très rapidement un lien pour atteindre les différents utilisateurs pour faire tous les tests ?
adamantyn
Messages postés
7
Date d'inscription
dimanche 8 mars 2015
Statut
Membre
Dernière intervention
17 juin 2019
Modifié le 17 juin 2019 à 01:10
Modifié le 17 juin 2019 à 01:10
Je ne suis pas sur de comprendre la question, dans le concret je fais : $member_id = $_SESSION['user_id']; ou $_SESSION['user_id'] est le numéro de l'utilisateur enregistré.
Quel lien vous voulez?
Oui je sais pour le GET, ca je comprends pourquoi ce n'est pas sécurisé.
C'est juste la partie du panier qui m'intéresse pour l'instant.
Quel lien vous voulez?
Oui je sais pour le GET, ca je comprends pourquoi ce n'est pas sécurisé.
C'est juste la partie du panier qui m'intéresse pour l'instant.
tpez
Messages postés
330
Date d'inscription
lundi 4 juillet 2016
Statut
Membre
Dernière intervention
17 juin 2019
39
17 juin 2019 à 07:37
17 juin 2019 à 07:37
Je ne vois pas de $_SESSION mais je vois juste ça dans ton code
J'aurais voulu un moyen pour changer d'utilisateur passer de utilisateur "2" à "3" ou "1" par exemple
$member_id = 2;
J'aurais voulu un moyen pour changer d'utilisateur passer de utilisateur "2" à "3" ou "1" par exemple
adamantyn
Messages postés
7
Date d'inscription
dimanche 8 mars 2015
Statut
Membre
Dernière intervention
17 juin 2019
Modifié le 17 juin 2019 à 12:00
Modifié le 17 juin 2019 à 12:00
Je voulais mettre le $_SESSION sur le site final.
J'ai mis en place un moyen de changer l'utilisateur de la même manière sur le site de démo:
https://adamantin.000webhostapp.com/tests/cart-custom/index.php
J'ai mis en place un moyen de changer l'utilisateur de la même manière sur le site de démo:
https://adamantin.000webhostapp.com/tests/cart-custom/index.php
16 juin 2019 à 16:13
Modifié le 16 juin 2019 à 16:30
Petite astuce pour coder en php :
possède un équivalent plus légé syntaxiquement qui est :
Je regarde les informations que tu m'as fourni et je réfléchis aux potentiels problèmes dans l'après midi.