sécurité et php...

sécurité et php... - PHP - Programmation

Marsh Posté le 29-12-2007 à 17:38:21    

Bjr,
j'essaye de créer un petit système d'authentification, et je cherche a boucher les trous de securité =) !

 


Code :
  1. //recupération des données du formulaire précedent
  2. $data[0] = $_POST['login'];
  3. $data[1] = $_POST['pass'];
  4. //lecture du couple pass/login ds la base de donnée
  5. $query ="SELECT login, pass FROM $table WHERE login='$data[0]'";
  6. $a = mysql_query($query, $idconexion);
  7. //signaler une erreur si le login n'est pas trouvé
  8. if ($a === false) {
  9. echo 'Login ou mot de passe invalide<br />';
  10.         echo '<a href="auth.html" title="retour a la page d\'authentification">retour</a>';
  11.         exit();
  12.         }
  13. //enregistrement ds le tableau $donnée[]
  14. $donnees = mysql_fetch_array($a);
  15. if( ( $donnees['login']==$data[0] ) ===false || ( $donnees['pass']==$data[1] )===false ) {
  16. //Si la conditon est rempli (echec de l'authentification)
  17. //alors on dirige (lien html) vers le formulaire d'authentification.
  18.  echo 'Login ou mot de passe invalide<br />';
  19.  echo '<a href="auth.html" title="retour a la page d\'authentification">retour</a>';
  20.  exit();
  21. //sinon on regenere l'id de session puis on authentifie l'utilisateur
  22. }else {
  23.  session_regenerate_id();
  24.  $_SESSION['auth']=1;
  25.  echo "identification ok<br />";
  26.  }
 

Mon code est-il vulnerable aux injections SQL ?
Je ne suis pas sur dans le sens où seul le login ($data[0]) est transmis dans la requete SQL et je ne voi pas quelle valeur peut lui permettre de fausser le resultat... (cf ligne 6 & 7)

 

contre le mal nommé 'cross site scripting', sufit il de filtrer les caractères "<" et ">" ?
quelles autres failles pouvez vous identifier ds ce code ? (les mdp st en clair mais c'est juste pr l'exemple...)

 

merci d'avance


Message édité par wrksx le 29-12-2007 à 17:45:33
Reply

Marsh Posté le 29-12-2007 à 17:38:21   

Reply

Marsh Posté le 29-12-2007 à 17:43:22    

houla!! renseigne toi sur l'injection SQL, parce que là, ça craint velu !
http://fr.wikipedia.org/wiki/Injection_SQL

 

Et je te suggère de t'acheter toi le dernier hors série MISC sur la sécurité si il est encore dispos.

 

vw


Message édité par Combi_A_Vendre le 29-12-2007 à 17:44:43
Reply

Marsh Posté le 29-12-2007 à 17:44:08    

Reply

Marsh Posté le 29-12-2007 à 17:50:16    

ce que j'aimerai ca serai un exemple de ce qu'un utilisateur malveillant pourrai faire et ce qu'il devrai entrer comme login pr le faire...

 

pdo ? en quoi ca aiderai pr mon pbleme ?


Message édité par wrksx le 29-12-2007 à 17:50:30
Reply

Marsh Posté le 29-12-2007 à 17:52:32    

Exemple, si je rentre comme login "admin '--", je suis bien enregistré comme utilisateur admin (si il existe) sans le mot de passe.

 

Et regarde bien en détails l'article wikipedia que je t'ai donné en lien.

 

vw


Message édité par Combi_A_Vendre le 29-12-2007 à 17:54:25
Reply

Marsh Posté le 29-12-2007 à 17:53:24    

non

 

j'ai qd meme pris la peine de verifier le mdp ensuite par php
cf ligne 18 stp...

 

mais merci de m'aider


Message édité par wrksx le 29-12-2007 à 17:54:28
Reply

Marsh Posté le 29-12-2007 à 17:56:00    

Pourquoi non?
Je t'avoue que je n'ai pas testé ton code, mais tu mets directement dans une requête ce que rentre l'utilisateur sans traitement, ce sont les conditions idéales d'une injection SQL.
 
vw

Reply

Marsh Posté le 29-12-2007 à 18:00:10    

ma requete est la suivante:
 
SELECT login, pass FROM $table WHERE login='$data[0]'
 
si $data[0] à été renseigné par l'utilisateur: admin'--
alors la requete devient:
SELECT login, pass FROM $table WHERE login='admin'--'
mais comme la verification n'a pas lieu à ca niveau...

Reply

Marsh Posté le 29-12-2007 à 18:01:18    

edit: c'es vrai qu'en réalité il ya injection de code, mais ce n'est pas nuisible j'ai l'impression...
edit2: oups :/


Message édité par wrksx le 29-12-2007 à 18:01:52
Reply

Marsh Posté le 29-12-2007 à 18:03:18    

Ca me parait clair que tu as une énorme faille de type injection SQL.
Login : ' OR ''='
Pass : un pass au hasard
 

Code :
  1. $query = "SELECT login, pass FROM $table WHERE login='$data[0]'";


devient :

Code :
  1. $query = "SELECT login, pass FROM $table WHERE login='' OR ''=''";


 
L'expression ''='' étant toujours vraie, la requête sélectionne toutes les lignes de ta table.


Message édité par CyberDenix le 29-12-2007 à 18:12:52

---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 29-12-2007 à 18:03:18   

Reply

Marsh Posté le 29-12-2007 à 18:15:28    

ah oui en effet...

Reply

Marsh Posté le 29-12-2007 à 18:20:42    

Tu peux t'en sortir avec mysql_real_escape_string, mais je te conseille de passer directement à PDO, qui échappe pour toi les entrées (pas d'oubli) et qui te permet de passer d'un SGBD à un autre assez facilement.
 
Dans un autre registre, je pense que tu peux t'instruire sur les failles de cross site scripting (vérifier que des données entrantes appartiennent à un domaine acceptable) et de man in the middle (la fonction hash est ton amie)


Message édité par CyberDenix le 29-12-2007 à 18:24:51

---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 29-12-2007 à 18:43:52    

pour le cross site scripting, un verification de "<" et ">" suffit-elle ?

Reply

Marsh Posté le 30-12-2007 à 10:35:40    

Non, pas du tout.
Regarde un peu ici : http://phpsec.org/projects/guide/fr/index.html


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 30-12-2007 à 15:39:57    

Le truc ultra important : addslashes();
 
Sinon : http://fr.wikipedia.org/wiki/Injection_SQL, cette doc est pas mal faite.


---------------
www.kobhqlt.no-ip.fr
Reply

Marsh Posté le 30-12-2007 à 16:10:30    

le truc super important les requêtes préparées, point :spamafote:

Reply

Marsh Posté le 30-12-2007 à 17:13:45    

Ok, je vais voir pour les requetes préparée plus tard, mais là je m'interesse aux details techniques car je m'initie au php.  
Il me parait important d'avoir bien compris les problèmes de cross-scripting et d'injection SQL avant d'adopter la solution parfaite (que je serais peut-être en mesure de choisir ensuite).
 
J'ai donc (temporairement) utilisé mysql_real_escape_string() comme on me l'a suggéré, ce qui fonctionne à merveille.
 
J'ai cru comprendre que le cross-scripting n'était possible que si les donnée envoyée par le client étaient retransmise au navigateur client.
 
Dans la mesure où ce test de page d'authentification n'affiche rien dans aucune page qui provienne du client (seul un test du couple pass/login est effectué sur la BD, d'où le pb d'injection SQL), je n'ai pas a craindre de cross-scripting sur mon site ?

Reply

Marsh Posté le 30-12-2007 à 17:29:48    

T'as lu le lien de CyberDenix :??:

Reply

Marsh Posté le 30-12-2007 à 18:03:10    

Voila ce que j'ai lu :
 

Citation :

Si vous affichez du contenu qui provient d'une source extérieure sans le filtrer de manière adéquate, vous êtes vulnérables aux XSS


 
http://phpsec.org/projects/guide/fr/2.html#2.3
 

Reply

Marsh Posté le 30-12-2007 à 21:12:47    

1 - Il est tres vivement conseillé d'echapper le nom des champs SQL
2 - Evite des concaténation hasardeuses genre :

Code :
  1. $chaine="SELECT champ FROM table WHERE champ1='$valeur' LIMIT 1";


Quand il faudrait faire:

Code :
  1. $chaine="SELECT champ FROM table WHERE champ1='".$valeur."' LIMIT 1";


D'ailleurs il a été démontré sur plusieurs sites que la déclaration de chaines avec des " au lieu de ' plus adaptés doublait presque le temps d'exécution dufait d'une tentative d'interpréter la chaine.
3 - evite de faire :

Code :
  1. if( ( $donnees['login']==$data[0] ) ===false || ( $donnees['pass']==$data[1] )===false )


Mais fais plutot (L'utilisation de l'operateur ternaire est assez discutable d'ailleurs ... ) :

Code :
  1. if( $donnees['login']!==$data[0]| ( $donnees['pass']!==$data[1] )
 

Je vois pas pourquoi tu fais un session_rgenerate_id() :??: si c'est pas bon, tu rediriges vers une autre page pour vider ton postDADA et tu raffiches ton form :)

 
kobhaltisapwner a écrit :

Le truc ultra important : addslashes();
Sinon : http://fr.wikipedia.org/wiki/Injection_SQL, cette doc est pas mal faite.


Que si les GPC sont désactivées ! Et d'ailleurs il est préférables d'utiliser mysql_real_escape_string() ou sprintf() :)

 

Enfin dernier p'tit truc :
evite de faire du echo directement dans le code. A la limite stocke dans une variable et fais un echo a la fin. Car si a un moment posterieur tu veux faire une redirection ou un envoi de header quelconque , ca sera impossible. Dans ton cas c'est pas important mais ca peux se révéler très utile sur d'autres script ;)


Message édité par the_bigboo le 30-12-2007 à 21:19:13
Reply

Marsh Posté le 31-12-2007 à 17:48:01    

Le "session_rgenerate_id()" est mal placé c'est vrai, je l'ai remonté en haut de la page juste sous le "session_start" pour prevenir la fixation de session.
 
Concernant les messages en echo, c'était pour l'exemple mais en réalité et comme tu le dit tt passe ds des variable car parfois une redirection intervient avant... Mais merci des details =)

Reply

Marsh Posté le 01-01-2008 à 20:04:56    

wrksx a écrit :

Voila ce que j'ai lu :
 

Citation :

Si vous affichez du contenu qui provient d'une source extérieure sans le filtrer de manière adéquate, vous êtes vulnérables aux XSS


 
http://phpsec.org/projects/guide/fr/2.html#2.3
 


 
Il s'agit de vérifier que toute donnée reçue correspond à une valeur acceptable, avant d'effectuer un traitement quelconque dessus (affichage, insertion dans une base de données, etc.).
 
Imagines que tu créées un formulaire d'inscription utilisateur avec une option sexe à Homme ou Femme, et qu'un petit rigolo recopies ton formulaire en local et y en ajoutant un troisième champ Extraterrestre. Il le sélectionne et pouf il s'incrit en tant qu'extraterrestre...
 
Pour éviter ça, tu peux par exemple créer une table sexe (id, name) avec deux valeurs :  
1 - Homme
2 - Femme
Puis tu regardes dans ta base de données si la donnée reçue correspond à une ligne de ta table sexe :  
SELECT 1 FROM sexe WHERE name = '...'
Si aucune ligne n'est sélectionnée, c'est que tu as (peut-être) une tentative de cross site scripting.
Sinon, tu peux inscrire ton utilisateur.


Message édité par CyberDenix le 02-01-2008 à 19:11:54

---------------
Directeur Technique (CTO)
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed