| | koala01 | Posté le 10/01/2005 @ 04:31 | Astucien
4715 Messages
| Beaucoup d'astuciens ont surement déjà remarqué que je n'appréciais que médiocrement les solutions de facilité qui consistent à utiliser des ressources toutes faites dans les sites personnels, qu'il s'agisse de forum (comme PhpBB) ou de portail (comme phpnuke)...
De même, ma méthode de réation "dynamique" des requetes SQL a de quoi en avoir surpris plus d'un avec l'utilisation quasi systématique de sprintf() au lieu des simples guillemets...
En effet, quand je fournis un code fait main, mes requetes SQL ressemblent généralement à
|
$sql=sprintf("SELECT * from table WHERE champs=`%d`",$variable_numérique);
|
M'attardant sur la lecture plus attentive de la documentation de php, je me rend compte que ce qui aux yeux de beaucoup (y compris des miens avant cette lecture) peut passer comme lubie d'amoureux de la programmation s'avaore en fait etre LA méthode permettant de sécuriser les échanges entre php et mysql...
Voici, pour vous faire une idée, quelques extraits de la doc...:
Injection SQL
De nombreux développeurs web ne sont pas conscients des possibilités de manipulation des requêtes SQL, et supposent que les requêtes SQL sont des commandes sûres. Cela signifie qu'une requête SQL est capable de contourner les contrôles et vérifications, comme par exemple les identifications et authentifications, et parfois, les requêtes SQL ont accès aux commandes d'administration.
L'injection SQL directe est une technique où un pirate modifie une requête SQL existante pour afficher des données cachées, ou pour écraser des valeurs importantes, ou encore exécuter des commandes dangereuses pour la base. Cela se fait lorsque l'application prend les données envoyées par l'internaute, et l'utilise directement pour contruire une requête SQL. Les exemples ci-dessous sont basés sur une histoire vraie, malheureusement.
[code]$offset = argv[0]; // Attention, aucune validation!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = mysql_query($query); [/code]
Un utilisateur normal clique sur les boutons 'suivant' et 'précédent', qui sont alors placés dans la variable $offset, encodée dans l'URL. Le script s'attend à ce que la variable $offset soit alors un nombre décimal. Cependant, il est possible de modifier l'URL en ajoutant une nouvelle valeur, au format URL, comme ceci :
[code]
0;
UPDATE user SET Password=PASSWORD('crack') WHERE user='root';
FLUSH PRIVILEGES;[/code]
Si cela arrive, le script va créer un nouveau Super utilisateur. Notez que la valeur 0; sert à terminer la requête originale et la terminer correctement.
|
Note : C'est une techinque répandue que de forcer l'analyseur SQL d'ignorer le reste de la requête, en utilisant les symboles -- pour mettre en commentaire.
|
Un moyen possible pour accéder aux mots de passe est de contourner la recherche de page. Ce que le pirate doit faire, c'est simplement voir si une variable du formulaire est utilisée dans la requête, et si elle est mal gérée. Ces variables peuvent avoir été configurées dans une page précédente pour être utilisées dans les clauses WHERE, ORDER BY, LIMIT et OFFSET des requêtes SELECT. Si votre base de données supporte les commandes UNION, le pirate peut essayer d'ajouter une requête entière pour lister les mots de passe dans n'importe quelle table. Utiliser la technique des mots de passe chiffrés est fortement recommandé.
...(suit une floppée d'exemple pour l'ajout d'utilisateur, la récupération ou la modification de mot de passe etc... Le poste sera déjà assez long comme cela [clindoeil])
Techniques de contournement
Vous pouvez prétendre que le pirate doit d'abord obtenir des informations sur le schéma de la base de données, dans la plupart des cas d'injections. C'est vrai, mais vous ne saurez jamais comment ni quand ces informations auront filtré, et si cela arrive, votre base de données sera en grand danger. Si vous utilisez une base de données Open Srouce, ou une base qui est du domaine public, ou encore un schéma qui appartient à un système de gestion de contenu ou d'un forum, le pirate peut facilement se procurer une copie du code que vous utilisez. Cela peut être un risque potentiel si la base a été mal conçue.
Ces attaques sont généralement basées sur l'exploitation de code qui n'est pas écrit de manière sécuritaire. N'ayez aucune confiance dans les données qui proviennent de l'utilisateur, même si cela provient d'un menu déroulant, d'un champ caché ou d'un cookie. Le premier exemple montre comment une requête peut causer un désastre. - Ne nous connectez jamais sur une base de données en tant que Super utilisateur ou propriétaire de la base. Utilisez toujours un utilisateur adapté, avec des droits très limités.
- Vérifiez que les données ont bien le type attendu. PHP dispose d'un éventail de fonction de validation large, depuis les plus simples, de la section Variables et la section Caractères (e.g. is_numeric(), ctype_digit() respectivement) aux fonctions avancées de Expression régulière Perl.
- Si l'application attend une entrée numérique, vérifiez vos données avec la fonction is_numeric(), ou bien modifiez automatiquement le type avec la fonction settype(), ou encore avec sprintf().[code]<?php
settype($offset, 'integer');
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// notez que %d dans la chaîne de format : %s serait inutile
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
$offset);
?> [/code]
- Mettez entre guillemet toutes les valeurs non numériques qui sont passées à la base de données, et protégez-vous des guillemets dans les valeurs avec la fonction addslashes() ou addcslashes(). Voyez le premier exemple. Comme les exemples l'on montré, les guillemets statiques peuvent être facilement contournés.
- N'affichez jamais d'informations spécifiques à la base, et notamment des informations concernant le schéma. Voyez aussi la section Rapport d'erreur et le chapitre Gestion des erreurs.
- Vous pouvez avoir des procédures stockées et des curseurs prédéfinis qui font que les utilisateurs n'ont pas un accès direct aux tables ou vues, mais cette solution a d'autres impacts.
A coté de ces conseils, il est recommandé d'enregistrer vos requêtes soit dans vos scripts soit dans la base elle-même, si elle le supporte. Evidemment, cet enregistrement ne sera pas capable d'empêcher une attaque, mais vous permettra de retrouver la requête qui a fauté. L'historique n'est pas très utile par lui-même, mais au niveau des informations qu'il contient. Plus vous avez de détails, mieux c'est.
|
A bon entendeur [clindoeil]
| | |
| |
| Publicité |
|
| | ti_ouf | Posté le 10/01/2005 à 17:30 | Astucien
4770 Messages
| bonjour
trés bonne info!!
| | | | | Malcolm | Posté le 10/01/2005 à 19:25 | Astucien
7309 Messages
| eh bé ...
on n'est plus en sécurité nulle part [bigsmile]
merci Koala [clindoeil] | | | |
| | Haut de la page |
| | Inscrivez-vous ! |
- Posez vos questions
- Résolvez vos problèmes
- Aidez les autres
- Participez et créez vos discussions
- Dialoguez en privé avec d'autres membres
- Suivez vos sujets préférés
- Affichez les signatures des membres
|
|