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 May Also Like

Comments

    1. Can you please clarify or share your test case?

      I am using the code below and cannot replicate your observed behavior.

      $barney = "A big purple dinosaur.";
      session_register("barney");
      
      echo $barney; // Prints A big purple dinosaur.
      
  1. Hi ,

    Can you please let me know where we have to add/edit this code in our application.

    Thanks,

    Nishitha Rachapalli

    1. on any file you’re going to need it, i’d suggest creating a globals.php file and require()’ing it on all your scripts

Leave a Reply

(optional)

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