[Wylug-help] PHP - register_globals OFF problem

Smylers@stripey.com Smylers at stripey.com
Sat, 11 Jan 2003 13:32:37 -0500 (EST)


On Fri, 10 Jan 2003, Andy Macdonald wrote:

> Just in case anyone else hasn't got an elegant way out of the
> register_globals OFF problem in PHP - well as elegant as PHP can be
> anyway!

Thanks.  I thought I'd got a hang on the many different approaches for
dealing with running older PHP scripts with register_globals off, but this
one was new to me.

> I found this nice function to handle global variables which can be
> added as a function in an include file for all scripts. Then all that
> is required is one line to declare the global variables and then they
> are available as before - no other code needs changing!

It's a fairly succinct way of declaring which variables you are expecting
from the user and ensuring that no others can be set from outside.

> As mentioned on the website referred to - this isn't much more secure
> than global variables as hackers just have to try each of the 5
> methods ... but see 'Example 5-16. Detecting simple variable
> poisoning' at the URL below, the idea of which I will try to
> incorporate into this function ..
>
> Ref: http://www.php.net/manual/en/security.registerglobals.php

Actually I think that "variable posoning" stuff is nonsense.  There seems
to be a fad among the kind of people who post in PHP forums for denouncing
any script using register_globals as insecure.  That simply isn't the
case.  (It's a good idea to use it, to prevent yourself making a stupid
mistake, but not using it doesn't necessarily mean that you have left a
vulnerability in your script.)

Without register_globals on, anybody viewing your page can set a global
variable in your script:

  http://localhost/admin.php?fruit=banana

So now your script has a variable called $fruit with the value 'banana'.
If you weren't previously using a variable of that name, then this is of
no consequence.  If you were using it but always initialized it yourself
then this also doesn't matter: your value will override the supplied one.

The security hole is only in scripts where a global variable is used
without being initialized :

  if (ValidSession() && !SessionTimeOut())
  {
    $logged_in = true;
  }
  # ...
  if ($logged_in)
  {
    ShowSecretInformation();
  }

(assuming the existence of the functions used).  The trouble is that
$logged_in is set to true when certain conditions are met and otherwise
left at it's default of false, making it susceptible to being set from the
URL.  It's easy to fix this however.  Explicitly setting all variables
will work:

  $logged_in = false;
  if (ValidSession() # ...

You can get PHP to inform you of variables you've used without
initialization by setting error_reporting to include E_NOTICE.

The "variable poisoning" mentioned in the manual page covers the
possibility of data coming from an unexpected source.  This strikes me as
a most peculiar thing to be concerned about.  Given that no data coming
from outside your script can be trusted, you always need to validate it
appropriately (and use encrypted session IDs or similar where
identification matters).

Yes, in theory a cracker _could_ view your HTML source, see that you are
expecting a form parameter called search and then create a cookie called
search instead with fake data in it.  But why do that rather than faking
the form parameter?  Your site needs to be safe from dodgy form data being
passed in -- and this applies irrespective of register_globals -- so so
long as you are validating data coming from users, how they get it there
doesn't really matter.

> in Comment by: djresonance at yahoo dot com
>
> "I think a better solution is to register each variable along with the
> request method from which that variable came seperatly.  To that end,
> I wrote a function which does exactly that.  This function accepts a
> variable number of arguments.  The first argument should be the
> request method you want to get the variable from, and the rest are the
> variables that you want to register in the global namespace.

So I disagree that this function doesn't provide much more security.
Using it and register_globals fixes the above $logged_in problem by
ensuring that $logged_in wouldn't be set even if passed in by a user
because it isn't in the list of things you declare as being user-set.

The thing I dislike about it is that you have to distinguish between get-
and post-submitted data.  I often want scripts to work with forms that
submit in either way, so that the method can be changed in the HTML
wihtout breaking the script.

Smylers