Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
J'ai bien saisi le risque des injections SQL et évidemment, je voudrais m'en prémunir.
J'ai commencé à chercher un peu sur le Net, mais ma "jeunesse" (c'est une notion toute relative ) en SQL me limite.
Bref, j'ai vu qu'en fonction de certains langage, il était possible de faire des requêtes paramétrées.
Pas de bol, je développe sous WINDEV et il semblerait que je ne puisse "que" envoyer des requêtes "classiques".
J'ai tenté de créer des fonctions, mais je suis toujours vulnérable lors du
SELECT * FROM mafonction(valeurs);
puisqu'il suffit de terminer une valeur avec un
'; injection SQL ; --
pour pouvoir prendre le contrôle sur la base.
J'ai bien 2 pistes pour améliorer la sécurité :
1 - faire une analyse de chaque champs de saisie et de transformer les ' en ''. Il ne me restera plus qu'à vérifier que le caractère d'échappement \ soit bien inactif (ou alors, le gérer également dans la mise en forme)
2 - utiliser les guillemets $$. Sachant que les balises peuvent comporter des valeurs entre les 2 $, cela laisse un sacré nombre de possibilités. D'autant plus qu'il est également envisageable d'utiliser un générateur de nombre aléatoire pour les balises.
Exemple :
SELECT * FROM matable WHERE colonne1 = $1234$chaine$1234
Par contre, est-ce qu'en cas d'erreur de requête, le message d'erreur renvoyé indique en clair les balises utilisées ? Du coup, dans ce cas, les $$ perdent toute utilité.
3 - Autre solution ?
Bref, est-ce que vous avez une idée pour m'aider à sécuriser mes requêtes SVP ?
Merci de votre attention.
Cordialement, Ramirez22
Hors ligne
Bonjour,
Jetez un oeil sur le "PREPARE" : https://docs.postgresql.fr/9.6/sql-prepare.html
Hors ligne
Bonjour et merci de la réponse.
Malgré tout, n'y a t'il pas possibilité d'injection (sauf erreur d'interprétation de ma part) ?
Petit exemple simple:
PREPARE recherche(text) AS SELECT * FROM matable WHERE colonne1= $1;
Il n'y a pas de risque pour la préparation puisque aucune valeur saisie par l'utilisateur n'est utilisée
EXECUTE recherche(maVariableContenantLaSaisieUtilisateur);
Si la variable contient : '%');DELETE FROM matable *; --' n'y a t'il pas de risque que la requête reçue par le serveur corresponde à :
EXECUTE recherche('%');DELETE FROM matable *; -- (tout ce qui suit n'a pas d'importance puisque considérée comme commentaire)
Cordialement,
Ramirez22
Hors ligne
Il faut faire un appel à quote_literal dans ce cas. Cela donnerait :
EXECUTE recherche(quote_literal(maVariableContenantLaSaisieUtilisateur));
(ce qui peut aussi se faire directement sur la première requête, sans passer par un PREPARE)
Guillaume.
Hors ligne
Bref, j'ai vu qu'en fonction de certains langage, il était possible de faire des requêtes paramétrées.
Dans WinDev aussi visiblement. Si je cherche "windev requêtes sql paramétrées" dans google et le 1er résultat est:
https://doc.pcsoft.fr/?2032050
avec ce style d'exemple:
SELECT * FROM CLIENT WHERE NOM = {Param1} AND PRENOM = {Param2}
HExécuteRequête(REQ_Clients_nom_prénom, hRequêteDéfaut, ...
"Dupond", "Jean")
Si vous ne voulez pas utiliser le système de Windev, il faut effectivement faire votre propre fonction d'échappement, l'équivalent du PQescapeLiteral () de la bibliothèque libpq (en C), ou du quote_literal() côté serveur.
Vous avez raison de remarquer que EXECUTE(paramètres) présente exactement le même risque qu'appeler une requête non préparée avec les mêmes paramètres. L'affirmation que requête préparée = protection contre les injections SQL est une sur-simplification. En réalité, si on utilise mal les requêtes préparées on est tout aussi vulnérable, et à l'inverse si on construit sa requête SQL avec des paramètres injectés mais en respectant à 100% les règles de syntaxe, il y a zéro risque avec les entrées malveillantes.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Merci de votre aide à tous.
Il faut faire un appel à quote_literal dans ce cas. Cela donnerait :
EXECUTE recherche(quote_literal(maVariableContenantLaSaisieUtilisateur));
(ce qui peut aussi se faire directement sur la première requête, sans passer par un PREPARE)
J'y ai vraiment cru
Hélas, lorsque je fais, par exemple :
EXECUTE recherche(quote_literal(maVariable));
Si je mets maVariable = bla
Je me retrouve avec une erreur car maVariable est remplacée par la valeur (normal) sans quote, donc erreur de postgreSQL : column "bla" does not exist at character ...
Si je mets maVariable = 'bla'
Je me retrouve sans erreur PostgreSQL, mais mes valeurs enregistrées sont fausse : un SELECT me retourne la valeur 'bla' (avec les quote).
EXECUTE recherche(quote_literal('maVariable'));
ou
set mavariable = 'bla' <= (Ce n'est qu'une représentation de l'affectation de mavariable)
EXECUTE recherche(quote_literal(maVariable));
SELECT * FROM matable
'bla'
Je pourrais par contre utiliser le $$ (je n'ai pas fait ce test).
[EDIT] Je viens de réaliser le test, les $$ sont remplacés par des '' et mes valeurs sont encadrées par un '... Dommage
Si vous ne voulez pas utiliser le système de Windev,
Exact, je ne veux pas utiliser le moteur HFSQL (système de PCSOFT / WINDEV) : il met des guillemets (") à chaque terme (les noms de colonnes, les valeurs...), il faut saisir la base de donnée sous l'outil WINDEV (double de boulot) + d'autres joyeusetés de ce genre.
Il est très bien quand on reste sous le système HFSQL client/serveur, mais je le trouve peu pratique lorsqu'on le fait causer avec PostgreSQL (certes il est possible de forcer la non correction des requêtes, mais ça commence à faire un peu beaucoup de manip'). De plus, je n'ai pas le choix dans la base de donnée (postgreSQL only dixit ma boite). Enfin, HFSQL a à priori quelques problèmes de sécurité et mon application est 'sensible'.
Je crois que je vais essayer de créer ma propre fonction d'échappement en m'inspirant de PQescapeLiteral(). Ça va demander un peu de boulot, mais je pense que la sécurité des requêtes SQL le vaut bien
Merci de vos interventions, si vous voyez d'autres pistes, je suis toujours curieux
Bonne soirée à toutes/tous
Ramirez22
Dernière modification par ramirez22 (07/11/2018 20:31:34)
Hors ligne
Bonjour,
Histoire de "terminer" ce Post et au cas où quelqu'un chercherait la même chose, voilà la procédure que j'ai créé sous Windev pour réaliser la fonction de doubler les quote automatiquement.
J'en ai profité pour supprimer les quotes multiples, afin de ne pas les doubler inutilement.
PROCEDURE Quote(sValeur est une chaîne)
i,j sont des entiers
i = 1
sChaineEntree, sChaineSortie sont des chaînes
sChaineEntree = sValeur
TANTQUE i <= Taille(sChaineEntree)
SI sChaineEntree[[i]] = "'" ALORS // si le caractère n'est pas un quote, on passe
j = i + 1
SI sChaineEntree[[j]] = "" ALORS // si le caractère suivant est vide, c'est qu'on arrive à la fin de la chaine
sChaineSortie += sChaineEntree[[i]] // on complète celle-ci
GOTO suite // et on passe à la phase de doublement des quote
FIN
TANTQUE j <= Taille(sChaineEntree) // par contre, si le caractère suivant n'est pas vide
SI sChaineEntree[[i]] = sChaineEntree[[j]] ALORS // on vérifie que ce n'est pas un quote aussi
j++ // dans l'affirmative, on passe au caractère suivant
SINON // sinon le quote est unique
sChaineSortie += sChaineEntree[[i]] // il est donc mis dans la chaine de sortie
i=j // et on passe au caractère suivant
SORTIR // (on passe directement au caractère non quote suivant)
FIN
SI j > Taille(sChaineEntree) ALORS // on vérifie si on est à la fin de la chaine
sChaineSortie += sChaineEntree[[i]] // si oui,on complète celle-ci
GOTO suite // et on passe à la phase de doublement des quote
FIN
FIN
SINON // le caractère n'est pas un quote (voir + haut)
sChaineSortie += sChaineEntree[[i]] // il est donc inscrit dans la chaine de sortie
i++
FIN
FIN
suite:
// Doublement des quote restantes pour qu'elles soient prises en compte comme caractère (et non comme fin de chaine)
sChaineSortie = Remplace(sChaineSortie,"'","''")
RENVOYER sChaineSortie
Évidemment, n'étant pas codeur professionnel, il y a sasns doute mieux à faire mais j'assume
Merci à tous de votre aide!
Bonne soirée.
Hors ligne
Pages : 1