Page 1 sur 2
injection sql: protection (changement de nom d'un precedent
Posté : 04 nov. 2007, 20:46
par choubix
j'ai cru comprendre qu'un danger avec les formulaire est "l'injection sql"
a mon niveau de debutant, est-il possible de se proteger contre cela facilement?
(j'ai lu qq infos sur Google qui m'ont un peu degrossi sur ce que c'est mais pas trop sur comment eviter que les champs de formulaire ne soient detournes de leur vocation premiere)
merci!
Posté : 04 nov. 2007, 21:33
par choubix
pour la securite des formulaires:
une petite recherche avec les BONS mots clefs m'a amene a trouver: mysql_real_escape_string()
a utiliser avec sprintf() afin d'eviter que les champs de formulaires soient proteges.
plus qu'a appliquer a tous les formulaires qui sont ouverts au public.
Posté : 05 nov. 2007, 02:33
par Power Web
Tu peux aussi utiliser htmlspecialchars() ou htmlentities() qui désactivé le HTML ainsi que addslashes() qui ajoutera des slash
Choisis entre les différentes car de mettre tout c'est ridicule
Perso, j'utilise htmlentities() avec la constante ENT_QUOTES qui convertit les guillemets doubles et les guillemets simples

Posté : 05 nov. 2007, 03:04
par choubix
salut Power Web,
j'ai regarde la doc sur mysql_real_escape_string(). ca semble interessant.
j'ai utilise cette syntaxe:
$query = sprintf("SELECT email FROM clients WHERE email='$email'",
mysql_real_escape_string($email));
$result = mysql_query($query) or die ('Invalid query: ' . mysql_error());
j'utilise aussi sur d'autres requetes lors de l'enregistrement d'un nouvel utilisateur.
je ne trouve pas de difference avec et sans en l'occurence.
je fais des verifications lorsque le formulaire est rempli qui evitent d'avoir des soucis par la suite.
je vais regarder dans les fonctions que tu recommandes.

Posté : 05 nov. 2007, 03:25
par Power Web
Bonsoir, moi en fait j'utilise mysql_real_escape_string() pour sécurisé les variables

Exemple:
if(isset($_POST['email']))
{
$email = mysql_real_escape_string(htmlentities($_POST['email'], ENT_QUOTES));
if(!empty($email))
{
$sql = mysql_query("INSERT INTO table VALUES($email)");
}
else
{
echo "Erreur : champs non remplis";
}
}
Tu comprends maintenant ? En fait on sécurise la variable $email ^^ pour l'insérer par la suite dans la BDD

Posté : 05 nov. 2007, 04:49
par choubix
je comprends que tu prends le champs email, tu traduit le contenu en html puis tu verifies qu'il n'y ai pas d'injection sql avec mysql_real_escape_string()
je suis dans le vrai?
de mon cote j'ai utilise la syntaxe donnee dans le manuel pour mysql_real_escape_string()
ils mettent la verification au niveau de la commande sql seulement.
je me suis demande si ca avait du sens.
par contre je me suis aussi dit que pour se premunir contre les injection sql:
- limiter le nombre de carateres
- rejeter automatiquement certains caracteres (via javascript par exemple)
- verifier que la syntaxe de l'email est bonne
ca devait deja faire une bonne partie du boulot non?
Posté : 05 nov. 2007, 11:03
par Berzemus
Oublie la limitation par javascript, il suffit de le désactiver pour passer outre.
Posté : 05 nov. 2007, 11:31
par Invité
comment tu as ruine tous mes espoirs de ne pas avoir a trop toucher a mes scripts toi!!
alros: est ce que ma syntaxe (qui est celle du manuel) suffit?
ou bien j'utilise cette de Power Web?
Posté : 05 nov. 2007, 11:51
par Berzemus
c'est dur la vie
Mais y'a plein de gens méchants, à l'affut de toute ouverture, et qui n'hésitent pas à te flinguer à la moindre occasion..
D'un manière générale, j'évite de faire des requêtes avec des données des utilisateurs, je les enregistre au préalable, je les compare, et j'effectue. Sauf bien sur quand je dois enregistrer des bazars dans une DB (avec, pour la sécurité, un utilisateur pour consulter et un autre pour enregistrer, si possible), ou envoyer un mail.. et un formulaire d'envoi de mail, c'est hyper-recherché, vu que c'est facilement exploitable.. un captcha me semble nécessaire, rien que pour empêcher l'envoi massif de mails.
Posté : 05 nov. 2007, 12:49
par Invité
hum: j'ai trouve pas mal de tutoriaux pour les captchas. reste a savoir ce que je fais...
ou alors je peux valdier a mano les emails a envoyer. mais bon: ca tue le charme du php qui me permet d'automatiser un maximum

Posté : 05 nov. 2007, 15:04
par Power Web
par contre je me suis aussi dit que pour se premunir contre les injection sql:
- limiter le nombre de carateres
- rejeter automatiquement certains caracteres (via javascript par exemple)
- verifier que la syntaxe de l'email est bonne
Salut,
Pour la limite tu peux faire ça via HTML
En changeant 30 par le nombre de caractères que tu veux
Ou PHP avec la fonction substr()
$email = substr($_POST['email'], 0, 30); // Pareil tu changes 30 par le nombre que tu veux
Pour la syntaxe de l'email tu peux utiliser une regex avec preg_match()
if(preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_POST['email']))
{
// Bon email
}
else {
// Mauvais email
}
Et pour interdire les caractères je sais pas ... Mis à part les regex peut-être
Comme ça :
if(preg_match("#[ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\!\?\:\.]#i", $_POST['email']))
{
echo "Votre email ne doit pas contenir de caractères spéciaux";
}
Ou tu remplaces tout simplement les caractères spéciaux avec la fonction strtr()
Bon courage

Posté : 05 nov. 2007, 15:32
par h0_noMan
Pour l'email il serait plus simple de vérifier les caractères autorisés que ceux interdit.
[A-Za-z0-9.@-]
Posté : 05 nov. 2007, 16:13
par Victor BRITO
Une autre solution, lorsqu'on est en PHP 5 et qu'on est susceptible de passer d'un SGBD à un autre, consiste à utiliser les requêtes préparées de PDO, qui échappent automatiquement les caractères spéciaux.
<?php
// Tentative d'injection SQL
$identifiant = "Pierre' -- ";
$mdp = '';
$pdo = new PDO ('mysql:host=localhost;dbname=ma_base', 'root', 'mdp');
$requete_preparee = "SELECT identifiant FROM table WHERE identifiant=:identifiant AND mdp=:mdp";
$requete = $pdo -> prepare ($requete_preparee);
$requete -> execute (array (
':identifiant' => $identifiant,
':mdp' => md5 ($mdp);
));
$resultat = $requete -> fetch ();
// La dernière ligne aura de fortes chances de retourner un tableau vide (aucun résultat trouvé)
// L'injection SQL est donc voué à l'échec
?>
Cet exemple montre bien que, sans préparation de requête ou d'échappement de chaînes, j'enverrais la requête suivante :
Code : Tout sélectionner
SELECT identifiant FROM table WHERE identifiant='Pierre' -- AND mdp=''
qui ne serait pas la requête attendue (puisque la fin a été mise en commentaire) et me permettrait d'accéder à la partie membres sans nécessiter de mot de passe.

Posté : 05 nov. 2007, 16:25
par Power Web
Pour l'email il serait plus simple de vérifier les caractères autorisés que ceux interdit.
[A-Za-z0-9.@-]
Ouai en effet suis-je bête! Sinon on devrait écrire tout les caractères spéciaux que l'on ne veut pas... Juste un peu long

Posté : 05 nov. 2007, 16:29
par orgerix
Pour les données numériques, il faut verifier si ce sont des nombre avec la fonction is_numeric() car avec celles ci, les injections se font sans caractères spéciaux.