How to emulate register_globals directive and session_register()/session_unregister() functions

On December 31, 2018, security support for PHP 5.6.x branch will officially cease, marking the end of all support for any version of the PHP 5.x branch. However PHP 5.x branch is still popular. According to statistics from W3Techs, about 60 percent of all web sites run on PHP 5.x branch. Therefore the following workaround to emulate register_globals directive may still be helpful for those trying to migrate legacy PHP code.

For a long time enabling register_globals directive was not recommended and could allow attacker to gain unauthorized access to the application. PHP community encourages the use of other means, such as the superglobals.

In my case the PHP application is for internal use only so the risk of someone attempting to attack was very minimal. Rewriting such a large application was not an option because the goal was to migrate the application to newer environment in short amount of time.

This migration guide from PHP 5.2 to PHP 5.6 was very helpful as well as these official guides (PHP 5.3, PHP 5.4, PHP 5.5 and PHP 5.6).

Official PHP documentation mentions a method to emulate register_globals directive on the FAQ page. However it does not emulate all of the functionality. For example, when global variable is updated corresponding session variable is not. If you code relies on this behavior, suggested workaround won’t work.

Below is alternative emulation of register_globals directive and session_register()/session_unregister() functions that solves the problem with updating of session variables.


// Determines whether "register_globals" directive needs to be emulated
define('CFG_PHP_REGISTER_GLOBALS', true);

// If "register_globals" directive needs to be emulated
// and "register_globals" directive is no longer available (PHP 5.4+)
if(CFG_PHP_REGISTER_GLOBALS and !ini_get('register_globals')){
   /**
    * Emulates "register_globals" directive.
    * See http://php.net/manual/en/faq.misc.php#faq.misc.registerglobals
    */
   function register_globals(){
      $superglobals = array($_SERVER, $_ENV, $_FILES, $_COOKIE, $_POST, $_GET);
      foreach ($superglobals as $superglobal) {
         foreach($superglobal as $key => $value){
            // If there is a collision, don't overwrite the existing global variable
            if(!array_key_exists($key, $GLOBALS)){
               $GLOBALS[$key] = $value;
            }
         }
      }  

      if(isset($_SESSION)){ 
         foreach($_SESSION as $key => $value){
            // If there is a collision, don't overwrite the existing global variable
            if(!array_key_exists($key, $GLOBALS)){
               // Use assingment by reference to update session variable 
               // when global variable changes
               $GLOBALS[$key] = &$_SESSION[$key];
            }
         }
      }
   }

   // Emulate "register_globals" directive
   register_globals();
}

// If session_is_registered() function is no longer available (PHP 5.4+)
if (!function_exists('session_is_registered')){
   /**
    * Emulates session_is_registered() function.
    */
   function session_is_registered($key){
      return array_key_exists($key, $_SESSION);
   }
}

// If session_unregister() function is no longer available (PHP 5.4+)
if (!function_exists('session_unregister')){
   /**
    * Emulates session_unregister() function.
    */
   function session_unregister($key){
      unset($_SESSION[$key]);
   }
}

// If session_register() function is no longer available (PHP 5.4+)
if (!function_exists('session_register')){
   /**
    * Emulates session_register() function.
    */
   function session_register(){
      // If session_start() was not called before this function is called, 
      // an implicit call to session_start() with no parameters will be made.
      if(session_id() === ''){ session_start(); }

      $args = func_get_args();
      foreach ($args as $key){
         // If "register_globals" directive needs to be emulated
         // or if session variable is not registered
         if (CFG_PHP_REGISTER_GLOBALS or !session_is_registered($key)) {
            $_SESSION[$key] = array_key_exists($key, $GLOBALS) ? $GLOBALS[$key] : null;
         }

         // Use assingment by reference to update session variable 
         // when global variable changes
         $GLOBALS[$key] = &$_SESSION[$key];
      }
   }
}

You Might Also Like

Leave a Reply

You may use simple HTML to add links or lists to your comment. Also use <pre><code class="language-*">...</code></pre> to mark up code snippets. We support language-js, language-markup and language-css for comments.
(Optional)

This site uses Akismet to reduce spam. Learn how your comment data is processed.