Précédent   Forum des professionnels en informatique > Bases de données > MySQL > SQL Procédural
SQL Procédural Forum d'entraide sur les triggers, les procédures stockées et les fonctions en MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 02/07/2006, 16h00   #1
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Par défaut Facile de déclencher une erreur mysql_fetch_array

Bonjour,

Je viens de penser à un petit (gros ?) trou de sécurité dans le forum que j'ai programmé.
J'ai des liens comme ça :
Code :
1
2
 
http://www.site.com/sujet-choix.php?affichage=1&debut=10
ici ?debut=10 c'est le nombre de tuples à aller chercher. C'est une variable dont la valeur sert de paramètre à la requête sql.
Si on entre quoi que ce soit d'autre qu'un chiffre, la requête génère l'erreur suivante :

Code :
1
2
3
Warning: mysql_fetch_array(): supplied argument IS NOT a valid MySQL result resource IN /home.2/site/scripts/compte/compte/sujet-choix.php ON line 82
 
Warning: mysql_free_result(): supplied argument IS NOT a valid MySQL result resource IN /home.2/site/scripts/compte/compte/sujet-choix.php ON line 135

Bien sûr je filtre la variable $_GET[debut] par htmlspecialchars et mysql_real_escape_string.
Mais tout de même, je pense que le fait d'afficher ces erreurs est mauvais pour la sécurité, ne serait-ce que parce que cela donne des informations sur le serveur (même si pour le moment c'est un mutualisé).


Une solution consiste donc à n'exécuter la requête que si le masque est corrrect, sinon on ne fait rien.
Dans les autres pages je n'ai pas ce problème car il y a un url rewriting qui génère une page d'erreur.

Voilà, qu'en pensez-vous ? Je fais un preg_replace pour tester le masque de la variable ? Je le fais aussi sur les pages de l'url rewriting où c'est pas la peine sur celle-ci ?(j'ai déjà vu que yahoo affiche les pages avec des urls non rewritées).


Merci pour vos conseils (de pros si possible)
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/07/2006, 16h20   #2
Expert Confirmé
 
Avatar de Eusebius
 
Inscription : avril 2003
Messages : 3 286
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 3 286
Points : 3 155
Points : 3 155
Bonjour
Juste un point de vue très général sur la question :

- phase de développement : on affiche TOUTES les erreurs, et on se débrouille pour qu'il n'en apparaisse plus aucune. Effectivement il faut faire attention à ce qu'on appelle l'injection SQL, le fait de mettre autre chose que ce qui est attendu dans une requête. Il faut donc toujours vérifier la cohérence des informations fournies par l'utilisateur (et éviter les exécutions de code externe).
- phase de production: on n'affiche plus les erreurs, mais par contre on reste conscient qu'il n'est plus censé en avoir, alors on les fait interpréter par le script, et on prévient un admin, un développeur... (envoi d'un mail, écriture dans un journal)

dans le php.ini, il y a une valeur display_errors qui pourra donc être mise à Off en production. On pourra aussi utiliser log_errors et les valeurs associées.
On vérifiera avec soin toutes les valeurs de retour.

On peut également configurer un gestionnaire d'erreurs personnalisé avec la fonction set_error_handler.
Eusebius est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/07/2006, 16h33   #3
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Je te remercie de ta réponse Eusébius.
Bon je reprend :
Citation:
- phase de développement : on affiche TOUTES les erreurs, et on se débrouille pour qu'il n'en apparaisse plus aucune.
Ce n'est pas volontaire, je n'ai pas de mysql_error par exemple, simplement ça fait bugger le script, je ne peux rien y faire.

Citation:
Effectivement il faut faire attention à ce qu'on appelle l'injection SQL, le fait de mettre autre chose que ce qui est attendu dans une requête.
mysql_real_escape_string doit supprimer les risques déjà (ou très fortement les réduire, y'a toujours des bêtes du piratage, mais bon....). Cela étant ce n'est pas une raison pour laisser s'afficher le message d'erreur dont j'ai parlé.
Citation:
Il faut donc toujours vérifier la cohérence des informations fournies par l'utilisateur (et éviter les exécutions de code externe).
Le problème c'est que quand le champ est un input text qui peut recevoir n'importe quoi, on ne peut plus utiliser les expreg, il ne reste mysql_real_escape_string (ceci dit ce type de champ ne contiennent normalement pas de valeur passées en paramètre aux requêtes, donc pas de problème comme celui que je rencontre en ce moment).

Citation:
- phase de production: on n'affiche plus les erreurs, mais par contre on reste conscient qu'il n'est plus censé en avoir, alors on les fait interpréter par le script, et on prévient un admin, un développeur... (envoi d'un mail, écriture dans un journal)
Comment faire pour être averti par mail ou par requête sql qu'une erreur vient de se déclencher dans la page ?

Pour le reste c'est du mutualisé je ne crois pas pouvoir modifier le php_ini.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/07/2006, 17h08   #4
Expert Confirmé
 
Avatar de Eusebius
 
Inscription : avril 2003
Messages : 3 286
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 3 286
Points : 3 155
Points : 3 155
Juste histoire de préciser, ce que j'ai dit n'était pas personnalisé : j'ai pas forcément dit que tu ne faisais pas ce que je conseillais.

Citation:
Envoyé par JackBeauregard
Ce n'est pas volontaire, je n'ai pas de mysql_error par exemple, simplement ça fait bugger le script, je ne peux rien y faire.
Tu fais tes requêtes comme précisé dans ma signature ?

Citation:
Envoyé par JackBeauregard
Le problème c'est que quand le champ est un input text qui peut recevoir n'importe quoi, on ne peut plus utiliser les expreg, il ne reste mysql_real_escape_string (ceci dit ce type de champ ne contiennent normalement pas de valeur passées en paramètre aux requêtes, donc pas de problème comme celui que je rencontre en ce moment).
Si tu as des spécifications précises, tu dois pouvoir définir un certains nombre de critères pour chaque entrée, qui limitent déjà les possibilités d'erreur (i.e. c'est un nombre, il est compris entre tant est tant, il n'y a pas tel ou tel caractère...)

Citation:
Envoyé par JackBeauregard
Comment faire pour être averti par mail ou par requête sql qu'une erreur vient de se déclencher dans la page ?
Avec set_error_handler, tu peux spécifier une fonction à appeler en cas d'erreur. Cette fonction, c'est toi qui l'écris donc tu en fais ce que tu veux ! C'est très intéressant comme procédé.
Eusebius est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/07/2006, 17h23   #5
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Citation:
Tu fais tes requêtes comme précisé dans ma signature ?
Non je n'utilise pas die et mysql_error() sauf si j'ai une erreur quand je programme et encore en général j'y pense pas (j'ai peur d'oublier de l'enlever).
Dans le cas présent, la requête fonctionne bien, elle attend simplement un nombre et si on entre autre chose dans l'url (ce que l'on est pas censé faire...), alors ça fait bugger le script.
Je filtre l'entré, mais tout de même je crois que je vais faire un preg_replace() pour supprimer cette erreur.

Citation:
Si tu as des spécifications précises, tu dois pouvoir définir un certains nombre de critères pour chaque entrée, qui limitent déjà les possibilités d'erreur (i.e. c'est un nombre, il est compris entre tant est tant, il n'y a pas tel ou tel caractère...)
Je me demande si c'est vraiment la peine pour l'intégralité des formulaires.
Par exemple, j'ai un script qui réagit si $_POST['var']==1.
Je filtre la variable htmlentities(mysql_real_escape_string()) de toute façon. Mais si $_POST['var'] n'est pas égal à 1 ça ne fera rien c'est tout, la valeur n'est pas passée en paramètre à une variable contrairement au cas que j'ai expliqué au début.
Et si le gars m'envoit une injonction sql, elle atterira dans la base, mais cassée par mysql_real_escape_string().
Citation:
Avec set_error_handler, tu peux spécifier une fonction à appeler en cas d'erreur.
Ok, je connaissais pas cette fonction, merci de me la faire découvrir. ça m'a pas l'air évident à utiliser, mais quand je serai dessus je posterai à propos si nécessaire.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 15h29   #6
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
Dans mes developpement, j'aime controler ce que je donne à manger à ma base car il lui faut lui donner de la nourriture saine .
Là ou il attend une valeur numérique il y aura une une valeur numérique garantie. De plus je m'assure que cette valeur existe bien dans la base de données. Si c'est pas le cas c'est que quelqu'un s'amuse à changer les valeurs pour provoquer quelque chose.
Je fais en sorte limiter le maximum d'information passé en url ou champs caché. Je compte sur l'intégrité et la justesse des informations déjà présente.
L'entrée et la sortie de ma base de données passe toujours par un objet via les accesseurs correspondant ainsi les variables sont typé (façon de voir); Exemple.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
Class Toto{
    private $id;
 
   public FUNCTION setId($pId){
      $this->id = (integer) $pId;
    }
 
  public FUNCTION getId(){
    RETURN (integer) $this->id;
  }
 
}
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 15h47   #7
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Code :
 ou il attend une valeur numérique il y aura une une valeur numérique garantie.
Ok mais souvent c'est des champs varchars et à part un htmlspecialchars(mysql_real_escape_string()) je vois pas trop quoi faire d'autre.

Citation:
Je fais en sorte limiter le maximum d'information passé en url ou champs caché.
Je les filtre aussi, donc pourquoi les limiter ?

En fait je vois pas comment le gars peut contourner un htmlspecialchars(mysql_real_escape_string()) sur chaque champ à part si c'est un pro et qu'il en veut vraiment. Pour certains script j'utilise quand même les expressions régulières.
Or justement le problème dans le cas que j'ai évoqué c'est que les valeurs ne sont pas envoyées dans la base (auquel cas mysql_real et htmlspecialchars font l'affaire) , mais sont passées en paramètre à la requête sql : et là ça déclenche un bug, parce que les valeurs ne sont pas conformes à celle attendues : d'où la nécessité de controler la nature des valeurs passées à la requêtes.

Mais tu me déclenches un doute : que ce passe-t'il si le pirate bidouille un faux formulaire pour trafiquer les champs hidden et s'en sert pour balancer des données qui ne correspondent pas à la nature du champ censé les recevoir (par exemple un champ smallint qui reçoit des chars, mêmes filtrées par les fonctions déjà évoquées) ?
Cela va-t'il déclencher un bug fatidique utilisable par le pirate ?
Dans mon expérience, les données ne sont simplement pas enregistrées mais c'est à vérifier.
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 16h45   #8
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
pour eviter qu'une personne puisse faire sa propre page et post sur ton serveur. Je place toujours en bas de mon fichier php un
session['from'] = $_SERVER['SCRIPT_NAME'].
Même si le pirate arrive a avoir la session il ne peut pas modifier son contenu et le faire mentire.

Concernant les filtres sur l'url c'est que je veux pas qu'un pirate puisse manipuler les données et créer des incohérence. Je donne un exemple.
Je veux récupérer un produit #23 qui se trouve dans la categorie #12
...?idcategorie=12&idproduit=23

Pour moi ça c'est une erreur de conception mais que nous retrouvons assez souvent. De plus selon les interactions ça peut poser problème. Que se passe t'il s'il place un idproduit qui ne se trouve pas dans la catégorie indiqué ???


C'est en ça que je parle de limiter les informations passé en url
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 18h21   #9
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Citation:
pour eviter qu'une personne puisse faire sa propre page et post sur ton serveur. Je place toujours en bas de mon fichier php un
session['from'] = $_SERVER['SCRIPT_NAME'].
Même si le pirate arrive a avoir la session il ne peut pas modifier son contenu et le faire mentire.
L'idée a l'air pas mal du tout, mais je ne pige pas du tout son fonctionnement.
Je viens de tapper session['from'] dans google, je n'ai rien trouvé, idem pour $_SERVER['SCRIPT_NAME']. Je ne pige pas ce que tu entends par là, ni comment ça peut fonctionner.

Citation:
Concernant les filtres sur l'url c'est que je veux pas qu'un pirate puisse manipuler les données et créer des incohérence. Je donne un exemple.
Je veux récupérer un produit #23 qui se trouve dans la categorie #12
...?idcategorie=12&idproduit=23

Pour moi ça c'est une erreur de conception mais que nous retrouvons assez souvent. De plus selon les interactions ça peut poser problème. Que se passe t'il s'il place un idproduit qui ne se trouve pas dans la catégorie indiqué ???


C'est en ça que je parle de limiter les informations passé en url
Ok je vois le truc, donc tu fais un test pour savoir, dans ce cas, si l'id est bien dans une fourchette prédéterminée ? Le truc c'est d'ensérer le plus possible les données expédiées à la base dans des choix prédéterminés, en fait.
Bon ceci dit ce n'est pas cela qui va permettre au pirate de réussir son coup je pense. A moins que comme j'ai dit, le fait d'envoyer un varchar quand la table attend un int ne puisse déclencher une erreur, ce qui me semble n'est pas le cas, puisqu'alors la base refuse d'enregistrer la valeur, selon ce que j'ai pu voir.
Qui confirme/infirme (de toute façon je me vois mal faire une expression régulières pour tous les champs de mes tables et puis dans certains cas, les varchars justement, c'est impossible).
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 18h25   #10
Expert Confirmé
 
Avatar de Eusebius
 
Inscription : avril 2003
Messages : 3 286
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 3 286
Points : 3 155
Points : 3 155
Citation:
Envoyé par JackBeauregard
L'idée a l'air pas mal du tout, mais je ne pige pas du tout son fonctionnement.
Je viens de tapper session['from'] dans google, je n'ai rien trouvé, idem pour $_SERVER['SCRIPT_NAME']. Je ne pige pas ce que tu entends par là, ni comment ça peut fonctionner.
Peut-être qu'il voulait dire :
Code :
$_SESSION["from"] = $_SERVER["PHP_SELF"];
Histoire de vérifier la provenance ?
Mais ptet que j'ai pas compris, aussi
Eusebius est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 19h52   #11
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
Effectivement c'est une erreur de ma part. Je voulais dire $_SESSION['from'] comme ça aurait pu être toto .

Concernant la cohérance des information passé en url je voulais dire qu'il fallait éviter de passer trop d'information alors qu'il est possible de le récupérer dans le serveur. Exemple l'idarticle étant associé à une catégorie peut être récupéré par une jointure sql ou objet. Ce n'est qu'un exemple mais pour dire qu'avec une application bien ficelé il peut y avoir un minimum d'information qui transite. Moin d'information = moin de possibilité pour le pirate de créer des erreurs.

Quand tu parles du type de champs attendu . Si la table attend un int et on lui balance varchar il faut éviter que ça soit le SGBD qui contrôlle l'information mais bien avant. Si tu vois que le fruit est pourri tu vas pas le manger en te disant que tu fais confiance à ton estomac pour le rejeter c'est ton oeil et éventuellement ton nez qui t'on alerté.
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/07/2006, 20h32   #12
Inscrit
 
Inscription : juin 2006
Messages : 531
Détails du profil
Informations forums :
Inscription : juin 2006
Messages : 531
Points : 225
Points : 225
Bon je marque résolu, et je viens d'ouvrir un sujet plus général ici, parce que pour la question de ce post, la réponse est évidente : je dois utiliser les expreg pour filtrer les variables passées en paramètre via l'url à mes requêtes.

La suite ici :
http://www.developpez.net/forums/sho...81#post1127281


Merci à vous
JackBeauregard est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/07/2006, 16h55   #13
Membre habitué
 
Avatar de kivan666
 
Inscription : janvier 2006
Messages : 243
Détails du profil
Informations personnelles :
Âge : 28

Informations forums :
Inscription : janvier 2006
Messages : 243
Points : 137
Points : 137
Envoyer un message via Skype™ à kivan666
Par défaut mais quel interet ??

je viens de lire ce topic et un point m'échappe...
Ok, si l'utilisateur s'amuse à remplacer les paramètres de l'URL à la main il va réussir à déclencher une erreure SQL...
super... mais quel interet pour ce "hackeur" ?? voir une liste d'erreure ??
je veux dire, son but c'est de récupérer un pass, on d'effacer des données... afficher des erreure n'a aucun interet...
ou alors un point m'a achappé... merci de m'éclairer...
kivan666 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/07/2006, 20h14   #14
Expert Confirmé
 
Avatar de berceker united
 
Développeur informatique
Inscription : février 2005
Messages : 2 982
Détails du profil
Informations personnelles :
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : février 2005
Messages : 2 982
Points : 3 567
Points : 3 567
Le message d'erreur peut donner des informations assez précieuse pour un hackeur. Donner le chemin du fichier qui traite les opération sql par exemple. Il suffit qu'il se connecte directement sur ce fichier et travailler directement dessus. Par exemple a.php gère la sécurité d'entrée dans la base. b.php gere l'insertion en base. si l'hacker attaque directement b.php il a zappé la sécurité.
__________________
Mon avatar ? Ce n'est rien, c'est juste la tête que je fais lorsque je vois un code complètement frappa dingue !...
berceker united est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/07/2006, 21h13   #15
Membre habitué
 
Avatar de kivan666
 
Inscription : janvier 2006
Messages : 243
Détails du profil
Informations personnelles :
Âge : 28

Informations forums :
Inscription : janvier 2006
Messages : 243
Points : 137
Points : 137
Envoyer un message via Skype™ à kivan666
mmm je vois... je n'y avais pas pensé car chez moi tout est toujours dans la même page...
kivan666 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 13h31.


 
 
 
 
Partenaires

Hébergement Web