SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 27
  1. #1
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Globals overwrite and its consequences

    Globals overwrite and its consequences

    So what are the consequences of this? I only got a chance to skim this article this morning and I have a meeting for the next few hours. Is this a big deal?

  2. #2
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The message is - if you have register_globals enabled, or even are just emulating this behaviour by something like extract($_REQUEST), you are vulnerble to execution of arbitrary code. The problem is worse with php4, since PEAR can be used as a host for this trick, so any site using PEAR + register_globals has its gates unbarred. Scary.

    Bottomline : set register_globals = Off

  3. #3
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Bottomline : set register_globals = Off
    Agree that's the bottom line but...

    The message is - if you have register_globals enabled, or even are just emulating this behaviour by something like extract($_REQUEST), you are vulnerble to execution of arbitrary code. The problem is worse with php4, since PEAR can be used as a host for this trick, so any site using PEAR + register_globals has its gates unbarred. Scary.
    ...you also have to be using some code that's reading from the $GLOBALS array and doing something which is likely to cause a problem, which relatively rare from what I've seen.

    PEAR Error's error stuff we already knew was evil

    Otherwise I've most commonly $GLOBALS accessed when people want to access raw POST data (vs. URL encoded data) e.g. $GLOBALS['HTTP_RAW_POST_DATA'] (two alternatives I know of - here or $fp = fopen( "php://stdin", "r" ); ) - i.e. when you have a script that will be receiving something other than urlencoded data (e.g. a POSTed XML document).

    So I guess there's a reason to fix those references after all...

  4. #4
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, you will get no argument from me on register_globals = Off.

    However is there a best coding practice for using global variables that will allow you to run securely even if you should happen to end up running on older versions of PHP with register_globals = On?

  5. #5
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Am I right in saying that using global $var; to access the global variables instead of using $GLOBALS[] prevents this?

    Eg
    PHP Code:
    function load_language($lang)

        global 
    $include_path;
        include 
    $include_path."/lang/$lang.php";

    As not relying on $GLOBALS.

  6. #6
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Neither is actually a goot practice. By using global variables within your functions you lose control over which data enters the functions.

    Functions -- both procedural ones and OOP methods -- should be well isolated (aka encapsulated), meaning that they work only with variables defined within them. Any outside values should enter them only through parameters, which have to be explicitly stated (or possibly use default values) when the function is called. This way you ensure the integrity of your data, which improves security.

  7. #7
    simple tester McGruff's Avatar
    Join Date
    Sep 2003
    Location
    Glasgow
    Posts
    1,690
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    [comments deleted: I didn't read the first post & missed the point of this topic]
    Last edited by McGruff; Nov 5, 2005 at 02:29.

  8. #8
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by HarryF
    ...you also have to be using some code that's reading from the $GLOBALS array and doing something which is likely to cause a problem, which relatively rare from what I've seen.
    From what I understood, simply using PEAR is enough? And since a lot of applications does that, the implications are quite substantive.

    Quote Originally Posted by Selkirk
    However is there a best coding practice for using global variables that will allow you to run securely even if you should happen to end up running on older versions of PHP with register_globals = On?
    Normally you'd be able to disable it in a .htaccess file. Anyway - According to the manual, register_globals have been turned off per default since 4.2.0. That's ancient.

  9. #9
    SitePoint Zealot
    Join Date
    Feb 2003
    Posts
    156
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Many larger hosting companies have it turned back on again, because of customer complaints. Or they at least have the option for users to turn it back on again.

    You can do the following to protect yourself though:
    Code:
    if ( ini_get('register_globals')  && 
         ( isset($_REQUEST['GLOBALS'] ) || isset($_FILES['GLOBALS']) )) 
    {
        die("GLOBALS overwrite attempt");
    }

  10. #10
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by BerislavLopac
    Neither is actually a good practice.
    Agreed, but with things like PEAR having these problems, and probably myriad of other applications, would be nice to know a quickfix.

  11. #11
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well, security works best in layers. I'm asking for my own benefit. I try to avoid globals, but sometimes its very difficult or simply not worth it to do so.

    List of best practices concerning global variable security in PHP:
    1. register_globals = off
    2. Don't import globals yourself from the request variables
    3. Avoid globals unless they are absolutely necessary.
    4. Initialize all global variables before use
    5. Check for exploit attempts:
      PHP Code:
      if ( isset($_REQUEST['GLOBALS'] ) || isset($_FILES['GLOBALS']) ) {
          die(
      "GLOBALS overwrite attempt");


    How does this sound? I already do everything but the last.

    I've been trying to install some older versions of PHP to check this out. Unfortunately, I can't compile 4.1.0, 4.1.2, 4.2, 4.2.3, 4.3.0, 4.3.1, or 4.3.2 on my machine any more. And yes, I tried all those. I'm working my way up to the oldest version I can actually compile.

    Here is the code that I am worried about: wact.inc.php. I can't entirely control the environment that it will end up being run in. Here is the documentation for wact.inc.php.

    I'm not sure I see a way to avoid global variables with this code and still work in PHP 4.
    Last edited by Selkirk; Nov 1, 2005 at 10:53. Reason: Fixed wrong link

  12. #12
    SitePoint Guru dagfinn's Avatar
    Join Date
    Jan 2004
    Location
    Oslo, Norway
    Posts
    894
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Selkirk
    How does this sound? I already do everything but the last.
    Here's an idea which is probably insane, but let me try it: Have piece of code identify all the existing members of the superglobal arrays, look for plain variables that are identical to the corresponding superglobal array elements and run some checks on them, perhaps even delete them.

    Something like this, off the top of my head:
    PHP Code:
    foreach (array_merge($_GET,$_POST,$_SERVER /*etc*/) as $key => $value) {
        if ($
    $key == $value) unset($$key);


  13. #13
    SitePoint Wizard gold trophysilver trophy
    Join Date
    Nov 2000
    Location
    Switzerland
    Posts
    2,479
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    From what I understood, simply using PEAR is enough? And since a lot of applications does that, the implications are quite substantive.
    Good point.

    Here is the code that I am worried about: wact.inc.php. I can't entirely control the environment that it will end up being run in.
    That code itself looks fine because you're initializing the arrays. Perhaps there's a risk though that someone using WACT could do something silly e.g.

    PHP Code:
    foreach ( $_POST[$conf['someOption']] as $key => $val ) {
        
    $GLOBALS[$key] = $value;

    Think thats a risk in general though, rather than something specific to this problem.

    What about, instead of using an array, use an object and it's properties? As far as I know, there's no way to reference object properties directly via GET or POST and performance. Also, depending on PHP version I believe, attempts to reference and object property via an array will result in PHP error e.g.

    PHP Code:
    <?php
    $foo 
    = new stdClass;

    $foo->bar 1;

    $foo['x'] = 1;
    With PHP 5.0.5 this gives me "Fatal error: Cannot use object of type stdClass as array"

    I guess the performance hit will be small, compared to arrays, so long as you're not calling methods, but haven't confirmed that. That might mean wact.inc.php might start looking like;

    PHP Code:
    <?php
    /**
    *  A registry of classes and the files they are located in. 
    */
    $GLOBALS['WactClassRegistry'] = new stdClass;
    $GLOBALS['WactClassLoaders'] = new stdClass;

    /**
    * record the location of a class for future reference.
    */
    function WactRegisterClassLocation($class$file) {
        
    $GLOBALS['WactClassRegistry']->{$class} = $file;
    }
    Not sure if it's a good idea to use stdClass though - I remember in some PHP 5.0.0 betas it was not available (which suggests someone itching to depreciate it), although it's back in 5.0.5.

  14. #14
    SitePoint Enthusiast mjlivelyjr's Avatar
    Join Date
    Dec 2003
    Location
    Post Falls, ID, US
    Posts
    92
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    if you wanted to use stdClass you could always use:

    PHP Code:
    <?php
     
    if (!class_exists('stdClass')) {
         class 
    stdClass {}
     }
    ?>
    That would pretty much insulate you from any depracation issues.

    Back to the root issue, this article basically teaches us yet again that we just cannot trust any unchecked input and globally scoped variables are just plain dangerous.

    I have found that the best way to work around $GLOBAL overwrites is to just not use the $GLOBAL variable. Most uses of $GLOBAL within functions can be easily replaced by static class members in php5 or registry/singelton patterns in both php5 and php4.

    True, singletons and registries both are frequently used as bad examples of design. However most times use of global variables is considered worse which makes me okay with suggesting this :P.

    Take Stefan's php example:

    PHP Code:
     <?php
       $include_path 
    dirname(__FILE__)."includes/";
     
       include 
    $include_path."common.php";
       
       
    load_language('de');
     
       function 
    load_language($lang)
       { 
         
    // no need to check that $lang 
         // is a 'nice' language because 
         // only internally used
     
         
    include $GLOBALS['include_path']."/lang/$lang.php";
       }
     
    ?>
    A possible rewrite of this small segement in php5 could be:

    PHP Code:
     <?php
       
    class Configuration {
         static public 
    $include_path;
       }
     
       
    Configuration::$include_path dirname(__FILE__)."includes/";
     
       include 
    Configuration::$include_path "common.php";
       
       
    load_language('de');
     
       function 
    load_language($lang)
       { 
         
    // no need to check that $lang 
         // is a 'nice' language because 
         // only internally used
     
         
    include Configuration::$include_path."/lang/$lang.php";
       }
     
    ?>
    Now, I don't really condone the usage of static class variables in this way but I think it proves my point that there are other 'convenient' ways to skin the cat without the tokens '$GLOBALS' ever appearing in your code.
    Mike Lively
    Digital Sandwich - MMM MMM Good

  15. #15
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I've spent some time experimenting with this. Here is the impact summary as far as I can tell:

    You need to worry if your code accesses any global variables using the $GLOBALS[] super-global and there is any chance that you might run on a version of PHP < 5.0.5 or < 4.4.1 with register_globals=on, or if you use the function import_request_variables(), or the function extract() in global scope or if you copy request variables into global scope in any version of PHP.

    Understand that just because you initialized your global variable does not necessarily mean that you are safe. This security hole can inject around your initialization.

    Different aspects of this hole are fixed in different versions of PHP. I was not able to replicate the malicious behavior using register_globals=on in PHP 5.0.4, although the article seems to suggest that I should be able to. I can replicate the problem in 5.0.4 with import_request_variables() and with extract().
    Last edited by Selkirk; Nov 5, 2005 at 09:04. Reason: Removed bad recommendation

  16. #16
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It seems to me that 'globals getter' $GLOBALS['x'] is a 'language construct' rather than array operator (at least in php 4). In fact, that getter construct has nothing to do with a variable named $GLOBALS, which is just an ordinary variable. Assignments to $GLOBALS have no impact on getter.

    PHP Code:
    $GLOBALS['x'] = 123;
    var_dump($GLOBALS['x']); // 123

    $GLOBALS 'icky'
    var_dump($GLOBALS); // icky
    var_dump($GLOBALS['x']); // still 123

    $GLOBALS = array('x' => 777);
    var_dump($GLOBALS); // x=>777
    var_dump($GLOBALS['x']); // still 123! 

  17. #17
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, this problem is more insidious that I thought. Unfortunately, $GLOBALS['var'] and global $var are not interchangeable as far as assign by reference is concerned:

    PHP Code:
    <?php
    $var 
    'initalized';
    function 
    assign() {
        
    $GLOBALS['var'] =& new StdClass();
    }
    assign();
    var_dump($var);
    ?>
    Outputs:
    Code:
    object(stdClass)#1 (0) { }
    while
    PHP Code:
    <?php
    $var 
    'initalized';
    function 
    assign() {
        global 
    $var;
        
    $var =& new StdClass();
    }
    assign();
    var_dump($var);
    ?>
    outputs
    Code:
    string(10) "initalized"

  18. #18
    SitePoint Enthusiast
    Join Date
    Feb 2004
    Location
    Montreal
    Posts
    77
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Selkirk, give this a try:
    PHP Code:
    $var 'initalized';
    function 
    assign() {
        global 
    $var;
        
    $var = new StdClass();
    }
    assign();
    var_dump($var); 
    The reason being is that the global keyword creates a reference. PHP's strange reference behavior really kicks in here. Not really sure how to explain it or even rationalize it, all I know is that that is how PHP works in that situation.

  19. #19
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here is a program that illustrates the nature of the problem:
    PHP Code:
    <?php

    extract
    (
        array(
    'GLOBALS' => array('secure' => 'injected1'), 'secure' => 'injected2')
        );

    class 
    TestClass {}

    echo 
    '<table border="1" cellpadding="20">';
    echo 
    '<TR><TH></TH><TH>global $secure</TH><TH>$GLOBALS[\'secure\']</TH></TR>';

    // $GLOBALS['secure'] = 'initialized';
    $secure 'initialized';

    echo 
    '<TR>';
    echo 
    '<TH>main scope after initialization</TH>';
    echo 
    '<TD>'var_dump($secure); echo '</TD>'
    echo 
    '<TD>'var_dump($GLOBALS['secure']); echo '</TD>';
    echo 
    '</TR>';

    function 
    AssignSecret() {
        global 
    $secure;

        echo 
    '<TR>';
        echo 
    '<TH>function scope before assign</TH>';
        echo 
    '<TD>'var_dump($secure); echo '</TD>'
        echo 
    '<TD>'var_dump($GLOBALS['secure']); echo '</TD>';
        echo 
    '</TR>';

        
    $GLOBALS['secure'] = 'assigned';
        
        echo 
    '<TR>';
        echo 
    '<TH>function scope after assign</TH>';
        echo 
    '<TD>'var_dump($secure); echo '</TD>'
        echo 
    '<TD>'var_dump($GLOBALS['secure']); echo '</TD>';
        echo 
    '</TR>';

    }

    function 
    RevealSecret() {
        global 
    $secure;

        echo 
    '<TR>';
        echo 
    '<TH>different function scope</TH>';
        echo 
    '<TD>'var_dump($secure); echo '</TD>'
        echo 
    '<TD>'var_dump($GLOBALS['secure']); echo '</TD>';
        echo 
    '</TR>';

    }

    AssignSecret();
    RevealSecret();

    echo 
    '<TR>';
    echo 
    '<TH>final main scope</TH>';
    echo 
    '<TD>'var_dump($secure); echo '</TD>'
    echo 
    '<TD>'var_dump($GLOBALS['secure']); echo '</TD>';
    echo 
    '</TR>';

    echo 
    '</table>';
    ?>
    Without the bug, and using any method to initialize the variable, one would expect the following output:
    Code:
    Expected behavior          global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "initialized"
    func scope before assign | "initialized"        "initialized"
    func scope after assign  | "assigned"           "assigned"
    different function scope | "assigned"           "assigned"
    final main scope         | "assigned"           "assigned"
    Lets initialize with $GLOBALS['secure'] = 'initialized' under PHP 4.3.4 in a malicious environment (represented by the extract statement):
    Code:
    Bug in PHP 4.3.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "injected2"          "initialized"
    func scope before assign | "injected2"          "injected2"
    func scope after assign  | "assigned"           "assigned"
    different function scope | "assigned"           "assigned"
    final main scope         | "assigned"           "initialized"
    Initializing in main scope using $GLOBALS['secure'] is obviously a dangerous placebo.

    Lets initialize with $secure = 'initialized'; under PHP 4.3.4:
    Code:
    Bug in PHP 4.3.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "injected1"
    func scope before assign | "initialized"        "initialized"
    func scope after assign  | "assigned"           "assigned"
    different function scope | "assigned"           "assigned"
    final main scope         | "assigned"           "injected1"
    well, almost looks workable as long as we avoid accessing the $GLOBALS array in main program scope, everything works as we would expect.

    Unfortunately, Lets see what happens when we try this in PHP 5.0.4 with $secure = 'initialized';
    Code:
    Bug in PHP 5.0.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "injected1"
    func scope before assign | "initialized"        "injected1"
    func scope after assign  | "initialized"        "assigned"
    different function scope | "initialized"        "assigned"
    final main scope         | "initialized"        "assigned"
    Insecure again. One more. Lets initialize with $GLOBALS['secure'] = 'initialized' under PHP 5.0.4:

    Code:
    Bug in PHP 5.0.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "injected2"        "initialized"
    func scope before assign | "injected2"        "initialized"
    func scope after assign  | "injected2"        "assigned"
    different function scope | "injected2"        "assigned"
    final main scope         | "injected2"        "assigned"
    It looks like sticking with $GLOBALS is workable in PHP 5. Unfortunately, its deadly in PHP 4.

    Does your brain hurt, yet? Mine does.

  20. #20
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by b1ind
    Selkirk, give this a try:
    PHP Code:
    $var = new StdClass(); 
    Unfortunately, in PHP 4, that ends up creating a copy of the object, which comes with its own set of problems.

  21. #21
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, here is the next set of truth tables. The AssignSecret function in the previous program performs its assignment using $GLOBALS['secure']. Lets change that to:
    PHP Code:
    global $secure;
    $secure 'assigned'
    Initialize with $GLOBALS['secure'] = 'initialized'; in PHP 4.3.4:
    Code:
    Bug in PHP 4.3.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "injected2"          "initialized"
    func scope before assign | "injected2"          "injected2"
    func scope after assign  | "assigned"           "assigned"
    different function scope | "assigned"           "assigned"
    final main scope         | "assigned"           "initialized"
    initialize with $secure = 'initialized' in PHP 4.3.4:
    Code:
    Bug in PHP 4.3.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "injected1"
    func scope before assign | "initialized"        "initialized"
    func scope after assign  | "assigned"           "assigned"
    different function scope | "assigned"           "assigned"
    final main scope         | "assigned"           "injected1"
    initialize with $secure = 'initialized' in PHP 5.0.4:
    Code:
    Bug in PHP 5.0.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "injected1"
    func scope before assign | "initialized"        "injected1"
    func scope after assign  | "assigned"           "injected1"
    different function scope | "assigned"           "injected1"
    final main scope         | "assigned"           "injected1"
    Initialize with $GLOBALS['secure'] = 'initialized'; in PHP 5.0.4:
    Code:
    Bug in PHP 5.0.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "injected2"          "initialized"
    func scope before assign | "injected2"          "initialized"
    func scope after assign  | "assigned"           "initialized"
    different function scope | "assigned"           "initialized"
    final main scope         | "assigned"           "initialized"
    I hate this bug.
    Last edited by Selkirk; Nov 5, 2005 at 01:09.

  22. #22
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, last set of truth tables. This one deals with assign by reference. As I pointed out in a previous post assign by reference does not play well with the global keyword, so we only have to consider the case of assigning (in AssignSecret) using the $GLOBALS superglobal. So lets add a toy class:
    PHP Code:
    class TestClass {} 
    and an assignment:
    PHP Code:
    $GLOBALS['secure'] =& new TestClass(); 
    First the expected behavior:

    Code:
    Expected behavior          global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "initialized"
    func scope before assign | "initialized"        "initialized"
    func scope after assign  | "initialized"        TestClass
    different function scope | TestClass            TestClass
    final main scope         | TestClass            TestClass
    The expected behavior with a reference assignment is different than with a value assignment. Here we expect global $secure and $GLOBALS['secure'] to diverge inside the function as a result of the mystery of implementing the global keyword using references.

    Initialize with $GLOBALS['secure'] = 'initialized'; in PHP 4.3.4:
    Code:
    Bug in PHP 4.3.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "injected2"          "initialized"
    func scope before assign | "injected2"          "injected2"
    func scope after assign  | "injected2"          TestClass
    different function scope | TestClass            TestClass
    final main scope         | TestClass            "initialized"
    initialize with $secure = 'initialized' in PHP 4.3.4:
    Code:
    Bug in PHP 4.3.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "injected1"
    func scope before assign | "initialized"        "initialized"
    func scope after assign  | "initialized"        TestClass
    different function scope | TestClass            TestClass
    final main scope         | TestClass            "injected1"
    initialize with $secure = 'initialized' in PHP 5.0.4:
    Code:
    Bug in PHP 5.0.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "initialized"        "injected1"
    func scope before assign | "initialized"        "injected1"
    func scope after assign  | "initialized"        TestClass
    different function scope | "initialized"        TestClass
    final main scope         | "initialized"        TestClass
    Initialize with $GLOBALS['secure'] = 'initialized'; in PHP 5.0.4:
    Code:
    Bug in PHP 5.0.4           global $secure       $GLOBALS['secure']
                               --------------       ------------------
    main scope after init    | "injected2"          "initialized"
    func scope before assign | "injected2"          "initialized"
    func scope after assign  | "injected2"          TestClass
    different function scope | "injected2"          TestClass
    final main scope         | "injected2"          TestClass
    Last edited by Selkirk; Nov 5, 2005 at 08:55.

  23. #23
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, thats enough truth tables. Now, assuming:
    • You want to use a global variable.
    • You want to run securely even if register_globals is turned on (or if someone makes a stupid mistake)
    • You want to run on older versions of PHP
    • You want to run on both php 4 and php 5
    • You do not want to just detect the bug and die

    Is there a set of best practices for securely using global variables and meeting these requirements?

  24. #24
    SitePoint Guru
    Join Date
    Nov 2002
    Posts
    841
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, here is what I came up with by overlaying all the tables and seeing which cells held the expected results.

    Best practices for securely using global variables:
    1. Never use a global variable in the main program scope for any purpose, even just to initialize it.
    2. Never use the global keyword anywhere for any purpose.
    3. Always initialize your global variables before using them. To comply with #1, this must be done by calling a function for that purpose.
      PHP Code:
      function initializeMyGlobal() {
          
      $GLOBALS['myglobal'] = NULL;
      }
      initializeMyGlobal(); 


    Well, its 2:30AM and this is how i've spent my friday night. I am going to go to bed and dream about having a life.
    Last edited by Selkirk; Nov 5, 2005 at 08:56.

  25. #25
    SitePoint Guru BerislavLopac's Avatar
    Join Date
    Sep 2004
    Location
    Zagreb, Croatia
    Posts
    830
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's pretty obvious, but let me make this a bit more universal:
    PHP Code:
    function init_global($var)
    {
        
    $GLOBALS[$var] = null;


    // or even:

    function set_global($var$value null)
    {
        
    $GLOBALS[$var] = $value;



Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •